自訂可拖曳

可拖曳項目是指工作區中顯示的物件,可以拖曳及放置。這些類別會實作 IDraggable 介面。

您幾乎不會想在 Blockly 中新增可拖曳項目 (例如 multiselect 外掛程式,或變更現有物件處理拖曳的方式),因為您無法在 Blockly 中新增已算繪的物件。工作區中只能有方塊、泡泡和工作區註解。

職責

執行拖曳作業時,可拖曳項目有幾項責任:

  • 將 SVG 元素移至拖曳層
  • 平移 SVG 元素。
  • 觸發移動事件

導入作業

如要建立新的可拖曳項目,您必須實作 IRenderedElementIDraggable 介面。這會讓 Blockly 知道物件可見且可拖曳。

class MyDraggable extends IRenderedElement, IDraggable {}

傳回根 SVG 元素

getRootSvg 方法會傳回根層級 SVG 元素 (通常是「群組」),其中包含構成可拖曳檢視區塊的所有其他元素。

getSvgRoot() {
  return this.rootSvg;
}

可退回的移動裝置

isMovable 方法會傳回可拖曳項目目前是否可移動 (因為您可能想暫時停用物件的拖曳功能)。如果 isMovable 傳回 false,則會改為拖曳工作區。

isMovable() {
  return true;
}

退貨位置

getRelativeToSurfaceXY 方法會傳回 Coordinate,指定工作區座標中可拖曳項目的左上角位置。

工作區座標的原點位於工作區的絕對左側和絕對頂端。而且不會隨著工作區縮放或移動而改變。

getRelativeToSurfaceXY() {
  return this.loc;
}

開始拖曳

startDrag 方法會初始化可拖曳項目的拖曳作業。這個方法不會移動可拖曳項目。但您應儲存完成拖曳作業所需的任何資料或建構任何物件。包括在呼叫 revertDrag 時,還原拖曳作業所需的任何資料。

此外,SVG 元素也應變更為工作區的拖曳圖層,因此會顯示在任何其他元素上方。

此外,這個函式也會接收事件,您可以用來檢查按下的按鍵。舉例來說,這樣您就能以不同方式處理拖曳作業 (例如在拖曳時按下 Shift 鍵)。

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

拖曳

drag 方法實際上會移動可拖曳的物件。newLoc 位於工作區座標中,且也會傳遞事件,您可以使用該事件檢查按下的按鍵。

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

還原拖曳

revertDrag 方法會將可拖曳項目傳回拖曳開始時的位置。舉例來說,如果可拖曳項目放置在禁止移動的拖曳目標上,就會發生這種情況。

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

結束拖曳

endDrag 方法會清除拖曳作業,釋放所有儲存的資料或物件,並將可拖曳項目傳回原始圖層。

如果呼叫 revertDrag,系統一律會在 revertDrag 後呼叫 endDrag

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

選取

系統偵測到拖曳動作時,會根據選取的元素決定要拖曳的元素。

ISelectable

如要選取可拖曳的項目,該項目必須實作 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.
  }
}

設定選取範圍

呼叫 Blockly.common.setSelected() 即可設定所選元素。通常您會想在收到使用者的 pointerdown 事件時執行這項操作。

  constructor() {
    this.initSvg();

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

相容性

可拖曳項目可以實作其他介面,以便與 Blockly 中的其他系統互動。

可刪除

您可以實作 IDeleteable 介面,讓垃圾桶或其他刪除目標處置可拖曳項目。

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

可複製

您可以實作 ICopyable 介面來複製可拖曳項目,並定義 IPaster 來貼上項目。

如要進一步瞭解如何複製及貼上,請參閱「複製及貼上」一文。