可拖动对象是指存在于工作区中且可以拖放的已渲染对象。它们实现了 IDraggable
接口。
在极少数情况下,您可能需要向 Blockly 添加新的可拖动对象(例如,多选插件,或更改现有对象处理拖动的方式),因为您无法向 Blockly 添加新的渲染对象。工作区中唯一可以存在的渲染对象是块、气泡和工作区注释。
职责
在执行拖动操作时,可拖动对象承担着多项责任:
实现
如需创建新的可拖动对象,您必须实现 IRenderedElement
和 IDraggable
接口。这样,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
以允许粘贴可拖动对象。
如需详细了解复制粘贴,请参阅复制粘贴。