唯杰地图 logo唯杰地图
VJMAP
EN

lifecycle

vjmapext/references/entity/lifecycle.md 4.7 KB159 行
原文

本文回答:实体的增、删、改、查、选中生命周期 —— addEntity / deleteEntity / getEntities / 选择集 / changed()。

一、添加实体

const line = new LineEnt([0, 0], [100, 0]);
line.color = 0xff0000;
mapcadLayer.addEntity(line);

addEntity 会:

  1. 对 type==="INSERT" 的实体先 setBlocksRef(this.blocks) 注入块表引用
  2. 放入内部 store(实体 id 在构造时已由 EntityBase 生成,addEntity 不改 id)
  3. 触发 entity:added 事件(store 内发射)
  4. 标脏 → 下一帧重绘

批量添加:

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();

十一、常见坑

  1. addEntity 后调 clone 要再 addEntity:clone 不会自动加入。
  2. changed vs styleChanged:反方向用错后果不同——styleChanged() 只回写 color/line_width/effect_*;改 visible/fillColor/fillOpacity/layerId/lineType 等调了 styleChanged() 画面不变(静默无效)。反之 changed() 改样式只是性能浪费。
  3. delete 了还保留引用:store 清了但你的数组里仍有对象 → 内存泄漏。
  4. 地图未就绪就 addEntity:先 await map.onLoad() 再 map.addControl(cad);MapCadLayer 没有 ready() API,addControl 即触发 onAdd。