preview
本文回答:拖动 / 取点过程中的"实时预览图"用
Engine.drawPreviewEntity(ent)/Engine.drawPreviewEntities([e1, e2])+Engine.clearPreview()控制;通常配合PointInputOptions.callback(鼠标移动时被调用,参数是画布坐标 →Engine.canvasToWcs(canvasPt)转世界坐标)。命令结束 / 异常时一定要Engine.clearPreview()。
一、最小预览(圆心 + 拖半径)
class CirclePreviewCommand {
constructor() { this.center = null; }
async main() {
Engine.undoManager.start_undoMark('绘制圆');
try {
if (!await this.getCenter()) return;
const r = await this.getRadius();
if (r == null) return;
const c = new CircleEnt([this.center.x, this.center.y], r);
c.setDefaults();
Engine.addEntities(c);
} finally {
Engine.undoManager.end_undoMark();
Engine.clearPreview();
}
}
async getCenter() {
const opt = new PointInputOptions('指定圆心:');
const r = await Engine.getPoint(opt);
if (r.status !== InputStatusEnum.OK) return false;
this.center = r.value;
return true;
}
async getRadius() {
const opt = new PointInputOptions('指定半径:');
opt.useBasePoint = true;
opt.basePoint = this.center;
opt.callback = (canvasPt) => {
const wp = Engine.canvasToWcs(canvasPt);
const r = Math.hypot(wp.x - this.center.x, wp.y - this.center.y);
if (r > 0) {
const preview = new CircleEnt([this.center.x, this.center.y], r);
preview.setDefaults();
Engine.clearPreview();
Engine.drawPreviewEntity(preview);
}
};
const r = await Engine.getPoint(opt);
if (r.status !== InputStatusEnum.OK) return null;
return Math.hypot(r.value.x - this.center.x, r.value.y - this.center.y);
}
}
MCP 参考:vjcad/example/command/03withpreview.js。
二、隐藏默认橡皮筋线 + 自定义预览
const opt = new PointInputOptions('指定终点:');
opt.useBasePoint = true;
opt.basePoint = startPoint;
opt.hideRubberBand = true; // 关掉默认橡皮筋
opt.callback = (canvasPt) => {
const wp = Engine.canvasToWcs(canvasPt);
const previewLine = new LineEnt([startPoint.x, startPoint.y], [wp.x, wp.y]);
const endpointMark = new CircleEnt([wp.x, wp.y], 3);
previewLine.setDefaults(); endpointMark.setDefaults();
Engine.clearPreview();
Engine.drawPreviewEntities([previewLine, endpointMark]);
};
MCP 参考:vjcad/example/input/02getpointwithbase.js。
三、底层等价 API(pcanvas.drawControl)
const dc = Engine.pcanvas.drawControl;
dc.drawPreviewEntity(ent);
dc.drawPreviewEntities([e1, e2]);
dc.drawHighLightEntity(ent);
dc.previewGraphics.clear();
dc.setPreviewPosition(point);
dc.setPreviewRotation(angle);
dc.setPreviewScale(sx, sy);
dc.resetPreview();
MCP 参考:vjcad/doc/command/api-reference.md。
便捷封装(推荐):
| 便捷 API | 等价 |
|---|---|
Engine.drawPreviewEntity(ent) |
Engine.pcanvas.drawControl.drawPreviewEntity(ent) |
Engine.drawPreviewEntities([e1, e2]) |
Engine.pcanvas.drawControl.drawPreviewEntities([...]) |
Engine.clearPreview() |
Engine.pcanvas.drawControl.clearPreview()(先移除 MText 等子容器再 previewGraphics.clear();只调 previewGraphics.clear() 清不掉 MText 预览) |
来源:示例 vjcad/example/command/03withpreview.js、vjcad/example/input/02getpointwithbase.js 中实际用 Engine.drawPreviewEntity / Engine.clearPreview。
四、注意
callback拿到的是画布坐标,必须Engine.canvasToWcs(canvasPt)转世界坐标后再算长度 / 角度。- 每次
callback触发都要先Engine.clearPreview(),否则预览图会重叠。 - 注册命令的
main()返回(或抛异常)后,框架会自动drawControl.resetPreview(),finally里再Engine.clearPreview()属防御写法;脚本里直接调getPoint画预览(不经命令框架)时才必须自己清。Esc 让输入返回status === InputStatusEnum.Cancel,不会抛异常——finally主要用于保证end_undoMark()执行。
反例
- 直接把
canvasPt.x / canvasPt.y当作图纸坐标:会跟随屏幕不跟随图纸缩放。 callback里不 clear 直接drawPreviewEntity:预览图随鼠标增长而堆叠。
参考(官方文档 MCP)
- 文档:
vjcad/doc/command/index.md、vjcad/doc/command/api-reference.md - 示例:
vjcad/example/command/03withpreview.js、vjcad/example/input/02getpointwithbase.js、vjcad/example/input/06getkeyword.js