Перетаскиватель — это объект контроллера, который координирует перетаскивание перетаскиваемых объектов в ответ на взаимодействие с пользователем.
Существует очень мало обстоятельств, когда вам захочется реализовать пользовательский перетаскиватель, потому что не так много того, что вы могли бы захотеть настроить в координации перетаскивания. Плагин 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,
},
});