Glisseurs personnalisés

Un outil de glisser-déposer est un objet de contrôleur qui coordonne le glissement des éléments déplaçables en réponse aux interactions de l'utilisateur.

Il est très rare que vous souhaitiez implémenter un outil de glisser-déposer personnalisé, car il n'y a pas grand-chose que vous puissiez personnaliser concernant la coordination d'un glisser-déposer. Le plug-in scroll-options implémente un outil de glisser-déposer personnalisé, car il souhaitait ajouter un défilement au bord de l'espace de travail, ce qui modifie la façon dont les coordonnées en pixels sont converties en coordonnées de l'espace de travail.

Responsabilités

Le dispositif de glisser-déposer a plusieurs responsabilités lors de l'exécution de glisser-déposer:

  • Appel des méthodes de glisser-déposer sur l'élément déplaçable.
  • Calcul de la position à laquelle l'élément déplaçable doit se déplacer en coordonnées d'espace de travail.
  • Appel des méthodes de cible de glissement sur les cibles de glissement sur lesquelles la souris est pointée.

Implémentation

Pour créer un outil de glisser-déposer personnalisé, vous devez implémenter l'interface IDragger.

class MyDragger implements IDragger {
  // Takes in the draggable being dragged and the workspace the drag
  // is occurring in.
  constructor(draggable, workspace);
}

Vous pouvez également sous-classer Blockly.dragging.Dragger intégré, qui gère déjà les responsabilités de base.

Démarrer les glissements

La méthode onDragStart initialise un glissement. Il doit stocker toutes les données nécessaires à l'exécution du glisser-déposer. Il doit également appeler startDrag sur l'élément draggable en cours de glisser-déposer.

onDragStart(e) {
  this.startLoc = this.draggable.getRelativeToSurfaceXY();

  this.draggable.startDrag(e);
}

Faire glisser

La méthode onDrag exécute un glisser-déposer. Il doit calculer la nouvelle position de l'espace de travail pour l'élément déplaçable en fonction de totalDelta, qui est indiqué en coordonnées de pixel.

Il doit également mettre à jour les cibles de glisser-déposer sur lesquelles vous pointez.

  • wouldDelete doit toujours être appelé avant d'appeler d'autres hooks sur la cible de glisser-déposer.
  • onDragExit doit toujours être appelé sur l'ancienne cible de glisser-déposer avant d'appeler onDragEnter sur la nouvelle cible de glisser-déposer.
  • onDragOver doit être appelé après onDragEnter la première fois que la cible de glissement est pointée, et à chaque appel supplémentaire de onDrag lorsque la cible de glissement est toujours pointée.
onDrag(e, totalDelta) {
  // Update the draggable location.
  const delta = this.pixelsToWorkspaceUnits(totalDelta);
  const newLoc = Coordinate.sum(this.startLoc, delta);
  this.draggable.drag(newLoc, e);

  // Call wouldDeleteDraggable.
  if (isDeletable(this.draggable)) {
    this.draggable.setDeleteStyle(
      // Checks that the drag target is an `IDeleteArea` and calls `wouldDelete`
      // on it.
      this.wouldDeleteDraggable(e, this.draggable),
    );
  }

  const newDragTarget = this.workspace.getDragTarget(e);
  if (this.dragTarget !== newDragTarget) {
    // Call `onDragExit` then `onDragEnter`.
    this.dragTarget?.onDragExit(this.draggable);
    newDragTarget?.onDragEnter(this.draggable);
  }
  // Always call `onDragOver`
  newDragTarget?.onDragOver(this.draggable);
  this.dragTarget = newDragTarget;
}

Mettre fin aux glissements

La méthode onEndDrag met fin à un glissement. Il doit informer l'élément draggable que le glisser-déposer est terminé et toute cible de glisser-déposer sur laquelle l'élément draggable a été déposé. Il doit également supprimer l'élément déplaçable si la cible de glissement est une zone de suppression.

  • onDrop doit toujours être appelé avant les autres méthodes.
  • revertDrag doit être appelé si la cible de glisser-déposer empêche les glissements.
  • endDrag doit être appelé après l'annulation du glissement, mais avant la suppression.
  • dispose doit être appelé si la cible de glisser-déposer est une zone de suppression.
onDragEnd(e) {
  // Call `onDrop` first.
  const dragTarget = this.workspace.getDragTarget(e);
  if (dragTarget) {
    this.dragTarget?.onDrop(this.draggable);
  }

  // Then revert the drag (if applicable).
  if (this.shouldReturnToStart(e, this.draggable)) {
    this.draggable.revertDrag();
  }

  // Then end the drag.
  this.draggable.endDrag(e);

  // Then delete the draggable (if applicable).
  if (
    isDeletable(this.draggable) &&
    this.wouldDeleteDraggable(e, this.draggable)
  ) {
    this.draggable.dispose();
  }
}

Inscription

Votre classe de glisseur doit être enregistrée pour pouvoir être créée lorsque des glissements sont détectés.

// Note that the type is BLOCK_DRAGGER even though draggers drag more than
// blocks. The name is for backwards compatibility.
Blockly.registry.register(registry.Type.BLOCK_DRAGGER, 'MY_DRAGGER', MyDragger);

Utilisation

Une fois que vous avez implémenté votre outil de glisser-déposer personnalisé, vous pouvez l'utiliser en le transmettant à vos options de configuration.

const myWorkspace = Blockly.inject('blocklyDiv', {
  plugins: {
    // Note that we pass this to blockDragger even though draggers drag more
    // than blocks. The name is for backwards compatibility.
    blockDragger: MyDragger,
  },
});