preview
本文回答:
PreviewManager.setPreviewEntities / clear—— 绘制命令里的橡皮筋实时预览。
一、是什么
用户在点第二个点之前,鼠标在动 → 实时显示一条"临时直线",跟随鼠标 → 点击确认才落地成真实实体。
这条"临时直线"就是 预览实体,由 PreviewManager 管。
二、API
ctx.previewManager.setPreviewEntities(entities: EntityBase[]): void
ctx.previewManager.setPreviewFeatures(features: GeoJSON.Feature[]): void
ctx.previewManager.setPolylineVertices(points: Point2D[]): void // 折线绘制中记录已确认顶点
ctx.previewManager.clearPolylineVertices(): void
ctx.previewManager.clear(): void // 注意:方法名是 clear(),不是 clearPreview()
ctx.previewManager.getFeatures(): GeoJSON.Feature[]
ctx.previewManager.setPreviewColor(hex: string | null): void // 覆盖预览色(默认跟 drawingDefaults.color)
三、和 getPoint 的 callback 搭配
PointInputOptions.callback(字段名是 callback,不是 onMouseMove)在光标移动时触发,参数是当前 CAD 坐标点:
class PreviewLineCmd {
async main(ctx) { // 实例方法,不能写 static
const { inputManager: im, previewManager: pm, store, drawingDefaults: defaults } = ctx;
const p1 = await im.getPoint({ message: '指定起点' });
if (p1.status !== 'ok') return;
const p2 = await im.getPoint({
message: '指定终点',
useBasePoint: true, // 橡皮筋开关是 useBasePoint,不是 rubberBand
basePoint: p1.value, // 点结果在 .value,不是 .point
callback: cur => {
const preview = new vjmapext.LineEnt(p1.value, cur); // 预览色由 pm 统一覆盖,设 color 无效
pm.setPreviewEntities([preview]);
}
});
pm.clear(); // 无论成功取消都清
if (p2.status !== 'ok') return;
const line = new vjmapext.LineEnt(p1.value, p2.value);
line.color = defaults.color;
store.add(line);
}
}
四、多预览实体
callback: cur => {
const line1 = new vjmapext.LineEnt(p1.value, cur);
const line2 = new vjmapext.LineEnt(p2.value, cur);
const marker = new vjmapext.CircleEnt(cur, 5);
pm.setPreviewEntities([line1, line2, marker]);
}
内部会把整组合并一次绘制,不闪。
五、getFeatures(序列化用)
const feats = pm.getFeatures();
// GeoJSON.Feature[],可叠加到其他图层或调试打印
六、与内置橡皮筋的区别
| 对象 | 内置橡皮筋 | setPreviewEntities |
|---|---|---|
| 触发 | getPoint({ useBasePoint: true, basePoint }) |
显式 set |
| 形状 | 只能一条直线 | 任意实体数组 |
| 样式 | 系统虚线 | 不继承实体颜色/线宽:color 被预览色覆盖(默认 = drawingDefaults.color),线一律 1px 虚线、点 4px;只保留多边形的 fillColor/fillOpacity |
| 用途 | 标准距离 / 方向显示 | 复杂形状 / 多对象预览 |
一般:
- 画 LINE → 只用橡皮筋够了
- 画 RECTPOLY / CIRCLE / 带文字的标注 → 用 setPreviewEntities
七、性能
setPreviewEntities 每次调用替换上一次内容;内部做了重绘合并,不需要手动 RAF。
但 callback 每帧都 fire → 如果每帧生成 100+ 预览实体可能卡;建议复用同一个实体对象:
const preview = new vjmapext.LineEnt(p1.value, p1.value);
callback: cur => {
preview.endPoint = cur;
pm.setPreviewEntities([preview]);
}
八、预览 Hatch 填充
callback: cur => {
const loop = [
p1.value,
[cur.x, p1.value.y], // 环用 [x,y] 数组(Point2DLike)
cur,
[p1.value.x, cur.y],
p1.value
];
const hatch = new vjmapext.HatchEnt(loop); // 构造收扁平点数组(>=3 点成 1 个 outer 环)
hatch.fillColor = 0xff0000;
hatch.fillOpacity = 0.3;
pm.setPreviewEntities([hatch]);
}
画矩形填充时的预览。
九、命令取消时的清理
try {
const p = await im.getPoint({ message: '...', callback: cur => { ... } });
...
} finally {
pm.clear(); // 无论 OK / Cancel 都清
}
或用 CommandContext 的生命周期:命令流程自然结束时 PreviewManager 会清掉,但显式 clear 更保险。
十、常见坑
- 忘
pm.clear():预览实体残留画面上(注意不是clearPreview(),那个方法不存在)。 - 预览实体被加到 store:预览不是 store 里的;不要
store.add(preview);只setPreviewEntities。 - 每帧 new 100 次 Entity:GC 压力大;复用同一个实体对象。
- 预览颜色 = drawingDefaults.color 看不清:给预览实体设
color没用(会被统一覆盖);改用pm.setPreviewColor('#ff00ff')换预览色(注意setDrawingDefaults会把它同步回默认色)。
相关
- 点输入 → input-manager
- 自定义命令 → custom-command
- 实体样式 → entity/style-props