拖曳

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