カスタム ドラッグ可能アイテム

ドラッグ可能なオブジェクトは、ワークスペースに存在するレンダリングされたオブジェクトで、ドラッグ&ドロップできます。IDraggable インターフェースを実装します。

Blockly に新しいドラッグ可能オブジェクトを追加する状況はほとんどありません(マルチセレクト プラグインや、既存のオブジェクトがドラッグを処理する方法を変更する場合など)。これは、Blockly に新しいレンダリング オブジェクトを追加できないためです。ワークスペース内に存在できるレンダリングされたオブジェクトは、ブロック、バブル、ワークスペースのコメントのみです。

責任

ドラッグを実行する際、ドラッグ可能な要素にはいくつかの役割があります。

実装

新しいドラッグ可能なアイテムを作成するには、IRenderedElement インターフェースと IDraggable インターフェースを実装する必要があります。これにより、Blockly はオブジェクトが表示され、ドラッグ可能であることを認識します。

class MyDraggable extends IRenderedElement, IDraggable {}

ルート SVG 要素を返します

getRootSvg メソッドは、ドラッグ可能なビューを構成する他のすべての要素を保持するルート SVG 要素(通常はグループ)を返します。

getSvgRoot() {
  return this.rootSvg;
}

可動性を戻す

isMovable メソッドは、ドラッグ可能なオブジェクトが現在移動可能かどうかを返します(オブジェクトのドラッグを一時的に無効にしたい場合があるため)。isMovablefalse を返した場合、代わりにワークスペースがドラッグされます。

isMovable() {
  return true;
}

戻り位置

getRelativeToSurfaceXY メソッドは、ワークスペース座標でドラッグ可能なアイテムの左上隅の位置を指定する Coordinate を返します。

ワークスペース座標の原点は、ワークスペースの絶対左上です。ワークスペースのスケールアップや移動を行っても変更されません。

getRelativeToSurfaceXY() {
  return this.loc;
}

ドラッグを開始

startDrag メソッドは、ドラッグ可能な要素のドラッグを初期化します。このメソッドは、ドラッグ可能な要素を移動しません。ただし、ドラッグを完了するために必要なデータやオブジェクトは保存する必要があります。これには、revertDrag が呼び出された場合にドラッグを元に戻すために必要なデータが含まれます。

また、svg 要素をワークスペースのドラッグレイヤに移動し、他の要素の上に表示されるようにする必要があります。

また、押されたキーを確認するために使用できるイベントも受け取ります。これにより、たとえば、シフト中のドラッグを通常のドラッグとは異なる方法で処理できます。

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 が呼び出されると、endDrag は常に revertDrag の後に呼び出されます。

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 を定義して、貼り付けできるようにします。

コピーと貼り付けの詳細については、コピーと貼り付けをご覧ください。