可拖动对象是存在于工作区中的渲染对象,可以对其进行拖放操作。它们实现了 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 元素更改为工作区的拖动层,使其位于任何其他元素的上方。
它还接受一个事件,您可以使用该事件来检查是否按下了键。这样,您就可以(举例来说)在移动时处理拖动操作,其处理方式与正常拖动操作不同。
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
以允许粘贴。
如需详细了解如何复制粘贴,请参阅复制粘贴。