Dragger 是控制項物件,可在回應使用者互動時協調拖曳 draggables。
您很少需要導入自訂拖曳工具,因為您不太可能需要自訂拖曳動作的協調方式。捲動選項外掛程式會實作自訂拖曳工具,因為它想在工作區邊緣新增捲動功能,藉此變更像素座標轉換為工作區座標的方式。
職責
執行拖曳動作時,拖曳器有幾項責任:
- 在可拖曳的元件上呼叫拖曳方法。
- 計算可拖曳項目在工作區座標中應移動的位置。
- 在任何懸停的拖曳目標上呼叫拖曳目標方法。
實作
如要建立自訂拖曳器,您必須實作 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,
},
});