lifecycle
本文回答:实体的增、删、改、查、选中生命周期 ——
addEntity/deleteEntity/getEntities/ 选择集 /changed()。
一、添加实体
const line = new LineEnt([0, 0], [100, 0]);
line.color = 0xff0000;
mapcadLayer.addEntity(line);
addEntity 会:
- 对
type==="INSERT"的实体先setBlocksRef(this.blocks)注入块表引用 - 放入内部 store(实体
id在构造时已由EntityBase生成,addEntity 不改 id) - 触发
entity:added事件(store 内发射) - 标脏 → 下一帧重绘
批量添加:
const ents = [line1, line2, circle, text];
ents.forEach(e => mapcadLayer.addEntity(e));
大量实体(万级):1.0.1 没有"暂停自动重绘"的 API——同步循环里连续 addEntity 本身就由 rAF 合并到下一帧一次渲染(每条仍会发 entity:added 并记一条 undo);量再大就分批或改用 GeoJSON 源渲染,见 batch/。
二、删除实体
mapcadLayer.deleteEntity(entity.id);
或直接用 store:
mapcadLayer.store.delete(entity.id);
清空:
mapcadLayer.store.getAllIds().forEach(id => mapcadLayer.store.delete(id));
// 或整体替换文档:mapcadLayer.fromJSON({ ...空文档 })
三、按 id 取实体
const ent = mapcadLayer.store.get(id);
四、枚举所有实体
const all = mapcadLayer.getEntities();
console.log(`共 ${all.length} 个实体`);
all.filter(e => e.type === 'LINE').forEach(line => {
line.color = 0x00ff00;
line.styleChanged();
});
五、选中操作
const selected = mapcadLayer.getSelectedEntities();
selected.forEach(e => { e.color = 0xffff00; e.styleChanged(); }); // 改样式要标脏
mapcadLayer.clearSelection();
程序化选中:
mapcadLayer.store.setSelection([entity.id]); // 单选(覆盖全集)
mapcadLayer.store.setSelection(ids); // 批量
mapcadLayer.store.setSelection(mapcadLayer.store.getAllIds()); // 全选
mapcadLayer.store.clearSelection(); // 清空
选中集由
EntityStore(_selectedIds)管理,变化时发selection:changed事件,详见 event/bus-selection。
六、通知系统重绘
| 调用 | 适用场景 | 代价 |
|---|---|---|
entity.styleChanged() |
仅改 color / lineWidth / effect_*(透明度类字段不在快路径) |
小 |
entity.changed() |
改几何(端点、半径、顶点…) | 中(会重算空间索引) |
mapcadLayer.getEntities().forEach(e => e.changed()) |
全量标脏(少用) | 大 |
entity.color = 0xff0000;
entity.styleChanged(); // 仅样式
// 以 LineEnt 为例,几何字段(startPoint 等)改完要标脏:
line.startPoint = new Point2D(10, 10); // line: LineEnt
entity.changed(); // 几何变化
不调会怎样:属性已改但画面没动。
七、克隆
const copy = entity.clone();
copy.color = 0xffff00;
mapcadLayer.addEntity(copy);
clone() 生成新 id,深拷贝几何和样式。
八、可见性
entity.visible = false;
entity.changed(); // visible 不在 styleChanged 快路径
批量隐藏某图层:
mapcadLayer.getEntities()
.filter(e => e.layerId === '标注层') // 字段是 layerId,不是 layer
.forEach(e => { e.visible = false; e.changed(); });
九、层级
mapcadLayer.moveToFront([id1, id2]);
mapcadLayer.moveToBack([id1]);
mapcadLayer.moveUp(ids);
mapcadLayer.moveDown(ids);
参数省略时作用于选中集。
十、撤销 / 重做
mapcadLayer.undo();
mapcadLayer.redo();
只有增删(store.add/store.delete,含 addEntity/deleteEntity)自动进撤销栈;改属性不会——程序化修改要先 undoManager.recordModify(ent) 再改(见 drawing/undo-redo)。批量操作可包成 transaction:
mapcadLayer.undoManager.beginTransaction(); // 批量导入
ents.forEach(e => mapcadLayer.addEntity(e));
mapcadLayer.undoManager.endTransaction();
十一、常见坑
- addEntity 后调 clone 要再 addEntity:clone 不会自动加入。
- changed vs styleChanged:反方向用错后果不同——
styleChanged()只回写color/line_width/effect_*;改visible/fillColor/fillOpacity/layerId/lineType等调了styleChanged()画面不变(静默无效)。反之changed()改样式只是性能浪费。 - delete 了还保留引用:store 清了但你的数组里仍有对象 → 内存泄漏。
- 地图未就绪就 addEntity:先
await map.onLoad()再map.addControl(cad);MapCadLayer 没有ready()API,addControl即触发onAdd。