Niestandardowe przeciąganie

Element przeciągania to obiekt kontrolera, który koordynuje przeciąganie elementów do przeciągania w odpowiedzi na interakcje użytkownika.

Wdrożenie niestandardowego selektora jest potrzebne w bardzo niewielu przypadkach, ponieważ nie ma zbyt wielu elementów, które można dostosować w ramach koordynacji przeciągania. Wtyczka opcji przewijania implementuje niestandardowy element przeciągania, ponieważ autor chciał dodać przewijanie na krawędzi obszaru roboczego, co zmienia sposób konwertowania współrzędnych pikseli na współrzędne obszaru roboczego.

Podmiot odpowiedzialny

Osoba wykonująca przeciąganie ma kilka obowiązków:

  • Wywoływanie metod przeciągania na elementach do przeciągania.
  • Obliczanie pozycji, do której należy przesunąć element przeciągalny w układzie współrzędnych obszaru roboczego.
  • wywoływanie metod docelowego elementu do przeciągania w przypadku dowolnego podświetlonego docelowego elementu do przeciągania.

Implementacja

Aby utworzyć niestandardowy element przeciągania, musisz zaimplementować interfejs IDragger.

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

Możesz też utworzyć podklasę wbudowanej klasy Blockly.dragging.Dragger, która już spełnia podstawowe obowiązki.

Rozpocznij przeciąganie

Metoda onDragStart inicjuje przeciąganie. Powinien on przechowywać wszystkie dane potrzebne do wykonania przeciągania. Powinien też wywoływać metodę startDrag obiektu draggable, który jest przeciągany.

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

  this.draggable.startDrag(e);
}

Przeciągnięcie

Metoda onDrag wykonuje przeciąganie. Powinien on obliczyć nową pozycję obszaru roboczego dla elementu przeciąganego na podstawie wartości totalDelta podanej w pikselach.

Powinien też zaktualizować wszystkie obiekty przeciągania, nad którymi znajduje się kursor.

  • Funkcja wouldDelete powinna być zawsze wywoływana przed wywołaniem innych funkcji obsługiwanych przez obiekt docelowy przeciągania.
  • Funkcja onDragExit powinna być zawsze wywoływana w starym docelowym obiekcie przeciągania przed wywołaniem funkcji onDragEnter w nowym docelowym obiekcie przeciągania.
  • Funkcja onDragOver powinna być wywoływana po onDragEnter pierwszym najechaniu kursorem na element do przeciągania oraz po każdym kolejnym wywołaniu funkcji onDrag, gdy element do przeciągania jest nadal podświetlony.
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;
}

Zakończ przeciąganie

Metoda onEndDrag kończy przeciąganie. Powinien on powiadomić obiekt, że przeciąganie zostało zakończone, a wszystkie obiekty, nad którymi znajduje się przeciągany obiekt, że został on upuszczony. Jeśli docelowy element jest obszarem do usuwania, należy również usunąć element przeciągany.

  • onDrop powinna być zawsze wywoływana przed innymi metodami.
  • Jeśli element do przeciągania uniemożliwia przeciąganie, należy wywołać funkcję revertDrag.
  • Funkcja endDrag powinna być wywoływana po odwróceniu przeciągania, ale przed usunięciem.
  • Funkcja dispose powinna być wywoływana, jeśli docelowy element przeciągania jest obszarem usuwania.
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();
  }
}

Rejestracja

Klasa obiektu przeciągania musi zostać zarejestrowana, aby można ją było utworzyć po wykryciu przeciągania.

// 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);

Wykorzystanie

Po zaimplementowaniu niestandardowego elementu przeciągania możesz go używać, przekazując go do opcji konfiguracji.

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,
  },
});