Niestandardowe elementy przeciągalne

Element do przeciągania to renderowany obiekt, który znajduje się w obszarze roboczym i można go przeciągać i upuścić. Implementują one interfejs IDraggable.

W Blockly rzadko kiedy dodaje się nowe elementy, które można przeciągać (np. w wtyczce do wielokrotnego wyboru lub w przypadku zmiany sposobu obsługi przeciągania przez istniejący obiekt), ponieważ nie można dodawać do Blockly nowych renderowanych obiektów. Jedynymi renderowanymi obiektami, które mogą znajdować się w obszarze roboczym, są bloki, dymki i komentarze do obszaru roboczego.

Podmiot odpowiedzialny

Elementy, które można przeciągać, mają kilka obowiązków podczas przeciągania:

Implementacja

Aby utworzyć nowy element, który można przeciągać, musisz zaimplementować interfejsy IRenderedElement i IDraggable. Dzięki temu Blockly wie, że obiekt jest widoczny i można go przeciągać.

class MyDraggable extends IRenderedElement, IDraggable {}

Zwracanie głównego elementu SVG

Metoda getRootSvg zwraca główny element SVG (zwykle grupę), który zawiera wszystkie pozostałe elementy tworzące widok elementu, który można przeciągać.

getSvgRoot() {
  return this.rootSvg;
}

Return movability

Metoda isMovable zwraca informację, czy element, który można przeciągać, jest obecnie przesuwalny (możesz chcieć tymczasowo wyłączyć przeciąganie obiektu). Jeśli isMovable zwróci wartość false, obszar roboczy zostanie przeciągnięty.

isMovable() {
  return true;
}

Pozycja zwrotu

Metoda getRelativeToSurfaceXY zwraca wartość Coordinate określającą położenie górnego lewego rogu elementu, który można przeciągać, we współrzędnych obszaru roboczego.

Współrzędne obszaru roboczego mają punkt początkowy w lewym górnym rogu obszaru roboczego. Nie zmieniają się one, gdy obszar roboczy jest skalowany lub przenoszony.

getRelativeToSurfaceXY() {
  return this.loc;
}

Rozpocznij przeciąganie

Metoda startDrag inicjuje przeciąganie elementu, który można przeciągać. Ta metoda nie przesuwa elementu, który można przeciągać. Musisz jednak przechowywać wszystkie dane lub tworzyć wszystkie obiekty, które są potrzebne do zakończenia przeciągania. Obejmuje to wszystkie dane, które będą potrzebne do przywrócenia stanu sprzed przeciągnięcia, jeśli zostanie wywołana funkcja revertDrag.

Powinien też przenieść elementy SVG do warstwy przeciągania obszaru roboczego, aby znajdowały się nad innymi elementami.

Przyjmuje też zdarzenie, którego możesz użyć do sprawdzenia, czy klawisze zostały naciśnięte. Dzięki temu możesz na przykład traktować przeciąganie z naciśniętym klawiszem Shift inaczej niż zwykłe przeciąganie.

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...
}

Przeciągnięcie

Metoda drag przenosi obiekt, który można przeciągać. Współrzędne newLoc są podane we współrzędnych obszaru roboczego. Przekazywane jest też zdarzenie, za pomocą którego możesz sprawdzić, czy klawisze zostały naciśnięte.

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

Cofanie przeciągania

Metoda revertDrag przywraca element, który można przeciągać, do pozycji, w której znajdował się na początku przeciągania. Dzieje się tak na przykład, gdy element, który można przeciągać, zostanie upuszczony na obszar docelowy przeciągania, który uniemożliwia ruch.

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

Zakończ przeciąganie

Metoda endDrag czyści przeciąganie, zwalniając wszystkie zapisane dane lub obiekty i przywracając element do przeciągania do pierwotnej warstwy.

endDrag jest zawsze wywoływana po revertDrag, jeśli revertDrag jest wywoływana.

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

Zaznaczenie

Element, który jest przeciągany, jest określany przez element wybrany po wykryciu przeciągnięcia.

ISelectable

Aby można było wybrać element, który można przeciągać, musi on implementować interfejs 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.
  }
}

Ustawianie wyboru

Wybrany element można ustawić, wywołując Blockly.common.setSelected(). Zwykle warto to zrobić w odpowiedzi na pointerdown zdarzenie od użytkownika.

  constructor() {
    this.initSvg();

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

Zgodność

Element przeciągany może implementować dodatkowe interfejsy, aby mógł wchodzić w interakcje z innymi systemami w Blockly.

Możliwe do usunięcia

Możesz zaimplementować interfejs IDeleteable, aby umożliwić usuwanie elementów, które można przeciągać, do kosza lub innych miejsc docelowych usuwania.

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.
  }
}

Można skopiować

Możesz zaimplementować interfejs ICopyable, aby umożliwić kopiowanie elementu, który można przeciągać, i zdefiniować interfejs IPaster, aby umożliwić jego wklejanie.

Więcej informacji o kopiowaniu i wklejaniu znajdziesz w artykule Kopiowanie i wklejanie.