Пользовательские перетаскиватели

Перетаскиватель — это объект контроллера, который координирует перетаскивание перетаскиваемых объектов в ответ на взаимодействие с пользователем.

Существует очень мало обстоятельств, когда вам захочется реализовать пользовательский перетаскиватель, потому что не так много того, что вы могли бы захотеть настроить в координации перетаскивания. Плагин scroll-options реализует пользовательский перетаскиватель, потому что он хотел добавить прокрутку на краю рабочей области, что изменяет способ преобразования координат пикселей в координаты рабочей области.

Обязанности

При выполнении перетаскивания у перетаскивателя есть несколько обязанностей:

  • Вызов методов перетаскивания для перетаскиваемого объекта.
  • Расчет позиции, в которую должен переместиться перетаскиваемый объект, в координатах рабочего пространства.
  • Вызов методов перетаскивания для любых перетаскиваемых целей, на которые наведен курсор.

Выполнение

Чтобы создать пользовательский перетаскиватель, вам необходимо реализовать интерфейс IDragger .

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

Вы также можете создать подкласс встроенного Blockly.dragging.Dragger , который уже выполняет основные обязанности.

Начать перетаскивание

Метод onDragStart инициализирует перетаскивание. Он должен хранить все данные, необходимые для выполнения перетаскивания. Он также должен вызывать startDrag для перетаскиваемого объекта.

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

  this.draggable.startDrag(e);
}

Тащить

Метод onDrag выполняет перетаскивание. Он должен вычислить новую позицию рабочей области для перетаскиваемого объекта на основе totalDelta , которая задается в пиксельных координатах.

Он также должен обновить все цели перетаскивания, на которые наведен курсор.

  • wouldDelete всегда следует вызывать перед вызовом других хуков для цели перетаскивания.
  • onDragExit всегда следует вызывать для старой цели перетаскивания перед вызовом onDragEnter для новой цели перетаскивания.
  • onDragOver следует вызывать после onDragEnter при первом наведении указателя мыши на цель перетаскивания и при каждом дополнительном вызове onDrag , когда цель перетаскивания все еще находится наведенным указателем мыши.
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;
}

Конец тянет

Метод onEndDrag завершает перетаскивание. Он должен уведомить перетаскиваемый объект о том, что перетаскивание завершено, а любую наведенную цель перетаскивания — о том, что перетаскиваемый объект был отпущен. Он также должен удалить перетаскиваемый объект, если целью перетаскивания является область удаления.

  • onDrop всегда следует вызывать перед другими методами.
  • revertDrag следует вызывать, если цель перетаскивания препятствует перетаскиванию.
  • endDrag следует вызывать после отмены перетаскивания, но перед утилизацией.
  • dispose следует вызывать, если целью перетаскивания является область удаления.
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();
  }
}

Регистрация

Ваш класс перетаскивателя должен быть зарегистрирован, чтобы его можно было создать при обнаружении перетаскивания.

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

Использование

После реализации пользовательского перетаскивателя вы можете использовать его, передав его в параметры конфигурации.

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