Éléments déplaçables personnalisés

Un élément déplaçable est un objet affiché qui existe dans l'espace de travail et qui peut être déplacé par glisser-déposer. Ils implémentent l'interface IDraggable.

Il existe très peu de cas où vous souhaiterez ajouter un nouvel élément déplaçable à Blockly (par exemple, le plug-in de sélection multiple ou la modification de la façon dont un objet existant gère les déplacements), car vous ne pouvez pas ajouter de nouveaux objets rendus à Blockly. Les seuls objets affichés pouvant exister dans un espace de travail sont les blocs, les bulles et les commentaires d'espace de travail.

Responsabilités

Les éléments déplaçables ont plusieurs responsabilités lors de l'exécution des opérations de déplacement :

Implémentation

Pour créer un élément déplaçable, vous devez implémenter les interfaces IRenderedElement et IDraggable. Cela indique à Blockly que votre objet est visible et peut être déplacé.

class MyDraggable extends IRenderedElement, IDraggable {}

Renvoie l'élément SVG racine.

La méthode getRootSvg renvoie l'élément SVG racine (généralement un groupe) qui contient tous les autres éléments constituant la vue de l'élément déplaçable.

getSvgRoot() {
  return this.rootSvg;
}

Retour de la mobilité

La méthode isMovable indique si l'élément déplaçable peut actuellement être déplacé (car vous pouvez souhaiter désactiver temporairement le déplacement d'un objet). Si isMovable renvoie false, l'espace de travail est déplacé à la place.

isMovable() {
  return true;
}

Position de retour

La méthode getRelativeToSurfaceXY renvoie un Coordinate spécifiant l'emplacement du coin supérieur gauche de l'élément déplaçable dans les coordonnées de l'espace de travail.

Les coordonnées de l'espace de travail ont une origine en haut à gauche de l'espace de travail. De plus, elles ne changent pas lorsque l'espace de travail est mis à l'échelle ou déplacé.

getRelativeToSurfaceXY() {
  return this.loc;
}

Démarrer le glisser-déposer

La méthode startDrag initialise un déplacement sur l'élément déplaçable. Cette méthode ne déplace pas l'élément déplaçable. Toutefois, vous devez stocker les données ou construire les objets dont vous avez besoin pour effectuer le déplacement. Cela inclut toutes les données dont vous auriez besoin pour annuler le déplacement si revertDrag est appelé.

Il doit également déplacer les éléments SVG vers le calque de déplacement de l'espace de travail, afin qu'ils se trouvent au-dessus de tous les autres éléments.

Il accepte également un événement, que vous pouvez utiliser pour vérifier les touches enfoncées. Cela vous permet (par exemple) de traiter un déplacement avec la touche Maj enfoncée différemment d'un déplacement normal.

startDrag(e) {
  // Save the original location so we can revert the drag.
  this.startLoc = this.getRelativeToSurfaceXY();

  // Disable resizing the workspace for performance.
  this.workspace.setResizesEnabled(false);

  // Put the element on the drag layer.
  this.workspace.getLayerManager()?.moveToDragLayer(this);

  // Fire a drag event...

  // etc...
}

Faire glisser

La méthode drag déplace réellement l'objet déplaçable. newLoc se trouve dans les coordonnées de l'espace de travail. Un événement est également transmis, que vous pouvez utiliser pour vérifier les touches enfoncées.

drag(newLoc, e) {
  this.moveTo(newLoc);
}

Annuler les déplacements

La méthode revertDrag renvoie l'élément déplaçable à la position qu'il occupait au début du déplacement. Cela se produit, par exemple, si l'élément déplaçable est déposé sur une cible de déplacement qui empêche le mouvement.

revertDrag() {
  // Move back to the position that was stored in `startDrag`.
  this.moveTo(this.startLoc);
}

Mettre fin aux déplacements

La méthode endDrag nettoie un déplacement, en libérant les données ou les objets stockés et en renvoyant l'élément déplaçable à son calque d'origine.

endDrag est toujours appelé après revertDrag si revertDrag est appelé.

endDrag() {
  // Put the element back on its original layer (in this case BLOCK).
  this.workspace
    .getLayerManager()
    ?.moveOffDragLayer(this, Blockly.layers.BLOCK);

  // Allow the workspace to start resizing again.
  this.workspace.setResizesEnabled(true);
}

Sélection

L'élément déplacé est déterminé par l'élément sélectionné lorsqu'un déplacement est détecté.

ISelectable

Pour être sélectionné, un élément déplaçable doit implémenter l'interface ISelectable.

class MyDraggable implements ISelectable {
  constructor(workspace) {
    this.id = Blockly.utils.idGenerator.genUid();
    this.workspace = workspace;
  }

  select() {
    // Visually indicate this draggable is selected.
  }

  unselect() {
    // Visually indicate this draggable is not selected.
  }
}

Définir la sélection

L'élément sélectionné peut être défini en appelant Blockly.common.setSelected(). En général, vous devez le faire en réponse à un événement pointerdown de l'utilisateur.

  constructor() {
    this.initSvg();

    Blockly.browserEvents.conditionalBind(
      this.getSvgRoot(),
      'pointerdown',
      this,
      () => Blockly.common.setSelected(this));
  }

Compatibilité

Votre élément déplaçable peut implémenter des interfaces supplémentaires pour interagir avec d'autres systèmes dans Blockly.

Éléments pouvant être supprimés

Vous pouvez implémenter l'interface IDeleteable pour permettre à votre élément déplaçable d'être supprimé par la corbeille ou d'autres cibles de suppression.

class MyDraggable implements IDeletable {
  isDeletable() {
    return true;
  }

  dispose() {
    // Dispose of any references to data or SVG elements.
  }

  setDeleteStyle() {
    // Visually indicate that the draggable is about to be deleted.
  }
}

Copiable

Vous pouvez implémenter l'interface ICopyable pour permettre la copie de votre élément déplaçable et définir un IPaster pour permettre son collage.

Pour en savoir plus sur le copier-coller, consultez Copier-coller.