编辑、选择与撤销
大约 5 分钟
编辑、选择与撤销
实体编辑、选择集操作、撤销系统。
实体变换
移动
const { LineEnt, Point2D, Engine } = vjcad;
const line = new LineEnt([0, 0], [100, 0]);
line.setDefaults();
Engine.addEntities(line);
// 移动实体:从 from 点移动到 to 点
line.move([0, 0], [50, 30]); // 支持 [x, y] 数组形式
// 必须重绘才能看到变化
Engine.regen();复制
// 使用 clone() 创建独立副本
const original = new LineEnt([0, 0], [100, 0]);
original.setDefaults();
Engine.addEntities(original);
const copy = original.clone();
copy.move([0, 0], [0, 50]); // 移动副本
copy.color = 2; // 修改副本属性
Engine.addEntities(copy); // 添加副本
Engine.regen();旋转
const { Point2D, Engine } = vjcad;
// rotate(basePoint, angle) - 绕基点旋转(角度为弧度)
const basePoint = new Point2D(50, 50); // 需要 Point2D 对象
entity.rotate(basePoint, Math.PI / 4); // 旋转 45°
Engine.regen();缩放
const { Point2D, Engine } = vjcad;
// scale(basePoint, scaleFactor) - 以基点为中心缩放
const basePoint = new Point2D(0, 0);
entity.scale(basePoint, 0.5); // 缩小到 0.5 倍
entity.scale(basePoint, 2.0); // 放大到 2 倍
Engine.regen();镜像
const { Point2D, Engine } = vjcad;
// mirror(p1, p2) - 沿 p1-p2 定义的直线镜像
const p1 = new Point2D(100, 0);
const p2 = new Point2D(100, 100);
entity.mirror(p1, p2); // 沿 x=100 垂直线镜像
Engine.regen();注意:
move()支持[x, y]数组形式rotate(),scale(),mirror()的点参数需要Point2D对象- 变换后必须调用
Engine.regen()才能看到变化
删除实体
const { Engine } = vjcad;
// 删除单个实体
Engine.eraseEntities(entity);
// 删除多个实体
Engine.eraseEntities([entity1, entity2, entity3]);
// 删除后 entity.isAlive 变为 false
console.log(entity.isAlive); // false绘图顺序
const { Engine } = vjcad;
// 方式1:使用命令
await Engine.editor.executerWithOp('ENTDRAWFRONT'); // 选中图形置于最前
await Engine.editor.executerWithOp('ENTDRAWBACK'); // 选中图形置于最后
await Engine.editor.executerWithOp('LAYDRAWFRONT'); // 选中图形的图层置于最前
await Engine.editor.executerWithOp('LAYDRAWBACK'); // 选中图形的图层置于最后
// 方式2:直接操作 items 数组
const items = Engine.currentSpace.items;
const idx = items.indexOf(entity);
if (idx > -1) {
items.splice(idx, 1); // 移除
items.push(entity); // 添加到末尾(最前面)
Engine.pcanvas.regen(true);
}分组
const { GroupEnt, LineEnt, CircleEnt, Engine } = vjcad;
// 创建实体
const line = new LineEnt([0, 0], [100, 0]);
const circle = new CircleEnt([50, 50], 20);
line.setDefaults();
circle.setDefaults();
// 创建组
const group = new GroupEnt("MyGroup", [line, circle]);
group.setDefaults();
Engine.addEntities(group);
// 访问组内实体
group.items.forEach((item, index) => {
console.log(`${index}: ${item.type}, 颜色: ${item.color}`);
});
// 炸开组
const explodedEntities = group.explode();
explodedEntities.forEach(ent => {
Engine.addEntities(ent);
});
Engine.eraseEntities(group);
Engine.regen(true);
// 使用命令
await Engine.editor.executerWithOp('GROUP'); // 创建组
await Engine.editor.executerWithOp('UNGROUP'); // 取消组高亮
const { Engine } = vjcad;
// 高亮指定实体
Engine.highLightEntities([entity1, entity2]);
// 清除高亮
Engine.clearHighLight();
// 高亮是临时视觉效果,不影响实体属性选择集操作
设置选择集
const { Engine } = vjcad;
// 选择单个实体
Engine.ssSetFirst([entity]);
// 选择多个实体
Engine.ssSetFirst([entity1, entity2, entity3]);
// 清空选择集
Engine.ssSetFirst([]);
// 选择所有实体
const allEntities = Engine.getEntities();
Engine.ssSetFirst(allEntities);获取选择集
const { Engine } = vjcad;
// 获取当前选择集
const selected = Engine.ssGetFirst();
console.log(`选中 ${selected.length} 个实体`);
// 遍历选择集
selected.forEach((entity, index) => {
console.log(`${index + 1}. 类型: ${entity.type}, 颜色: ${entity.color}`);
});
// 对选择集进行操作
selected.forEach(entity => {
entity.color = 1;
});
Engine.regen();获取实体
获取所有实体
const { Engine } = vjcad;
const allEntities = Engine.getEntities();按类型获取
const { Engine } = vjcad;
const lines = Engine.getEntitiesByType('LINE');
const circles = Engine.getEntitiesByType('CIRCLE');
const arcs = Engine.getEntitiesByType('ARC');
const plines = Engine.getEntitiesByType('PLINE');
const texts = Engine.getEntitiesByType('TEXT');
const mtexts = Engine.getEntitiesByType('MTEXT');
const inserts = Engine.getEntitiesByType('INSERT');
const hatches = Engine.getEntitiesByType('HATCH');按条件过滤
const { Engine } = vjcad;
// 按颜色过滤
const redEntities = Engine.getEntities(ent => ent.color === 1);
// 按图层过滤
const layerAEntities = Engine.getEntities(ent => ent.layer === "图层A");
// 组合条件
const redLines = Engine.getEntities(ent =>
ent.type === "LINE" && ent.color === 1
);
// 自定义复杂条件
const largeCircles = Engine.getEntities(ent =>
ent.type === "CIRCLE" && ent.radius > 50
);
// 排除某些实体
const notHidden = Engine.getEntities(ent =>
ent.layer !== "隐藏图层"
);撤销系统
基本撤销/重做
const { Engine } = vjcad;
const undoMgr = Engine.undoManager;
// 检查是否可撤销/重做
if (undoMgr.canUndo()) {
undoMgr.undo();
}
if (undoMgr.canRedo()) {
undoMgr.redo();
}撤销标记
const { Engine, Point2D } = vjcad;
const undoMgr = Engine.undoManager;
// 添加实体的撤销标记
undoMgr.added_undoMark([entity1, entity2]);
// 删除实体的撤销标记
undoMgr.erased_undoMark([entity1, entity2]);
// 移动操作的撤销标记
const fromPt = new Point2D(0, 0);
const toPt = new Point2D(40, 0);
entity.move(fromPt, toPt);
undoMgr.moved_undoMark([entity], fromPt, toPt);
// 旋转操作的撤销标记
undoMgr.rotate_undoMark(entities, basePoint, angle);
// 缩放操作的撤销标记
undoMgr.scaled_undoMark(entities, basePoint, scale);注意:Engine.addEntities() 和 Engine.eraseEntities() 会自动记录撤销。
撤销分组
将多个操作合并为一次撤销。
const { Engine, LineEnt, CircleEnt } = vjcad;
const undoMgr = Engine.undoManager;
// 开始撤销组
undoMgr.start_undoMark();
try {
// 执行多个操作
const line = new LineEnt([0, 0], [100, 0]);
line.setDefaults();
Engine.addEntities(line);
const circle = new CircleEnt([50, 50], 30);
circle.setDefaults();
Engine.addEntities(circle);
// 移动操作
line.move([0, 0], [50, 0]);
undoMgr.moved_undoMark([line], new Point2D(0, 0), new Point2D(50, 0));
} finally {
// 结束撤销组(必须确保调用)
undoMgr.end_undoMark();
}
// 撤销时会一次性撤销整个组内的所有操作视图操作
缩放
const { Engine } = vjcad;
// 缩放到全图
Engine.zoomExtents();
// 缩放到指定实体
Engine.zoomToEntities([entity1, entity2]);
// 带边距的缩放
Engine.zoomToEntities(entities, {
padding: { top: 50, bottom: 50, left: 50, right: 50 }
});刷新显示
const { Engine } = vjcad;
// render() - 最底层渲染,只执行 GPU 绘制
Engine.render();
// redraw() - 更新视图变换后渲染
Engine.redraw();
// regen() - 局部更新,只重绘已修改的实体(快)
Engine.regen();
// regen(true) - 完全重绘所有图形(慢)
Engine.regen(true);预览
const { Engine } = vjcad;
// 绘制预览实体
Engine.drawPreviewEntity(entity);
Engine.drawPreviewEntities([entity1, entity2]);
// 清除预览
Engine.clearPreview();设置视图中心
const { Engine, Point2D } = vjcad;
// 设置视图中心点
Engine.setCenter(new Point2D(100, 100));
// 带边距的设置
Engine.setCenter(new Point2D(100, 100), true, {
top: 50, bottom: 50, left: 50, right: 50
});背景色
const { Engine } = vjcad;
// 设置背景灰度值(0=纯黑, 255=纯白)
Engine.setBgc(0); // 纯黑
Engine.setBgc(33); // 深灰(默认深色主题)
Engine.setBgc(255); // 纯白
Engine.redraw();主题
const { Engine } = vjcad;
// 切换主题
Engine.THEME_MODE = 0; // 深色主题
Engine.setBgc(33);
Engine.redraw();
Engine.THEME_MODE = 1; // 浅色主题
Engine.setBgc(255);
Engine.redraw();
// 检查当前主题
const isDark = Engine.isDarkTheme();屏幕范围
const { Engine } = vjcad;
// 获取屏幕边界(世界坐标系)
const bounds = Engine.getScreenBoundsWcs();
// 返回: { minX, minY, maxX, maxY }
// 获取屏幕内的实体
const screenEntities = Engine.getScreenEntities();
const expandedEntities = Engine.getScreenEntities(1.5); // 扩展 1.5 倍范围缩放因子
const { Engine } = vjcad;
// 获取当前缩放比例
const zoom = Engine.currentSpace.zoom;
// 设置滚轮缩放因子(1-100,默认 75)
Engine.ZOOMFACTOR = 50; // 缩放更慢
Engine.ZOOMFACTOR = 100; // 缩放更快