bulk-style-update
本文回答:大量实体只改样式(
color/lineWidth/effect_*)时用styleChanged快路径,避免几何重算;visible/ fill / lineType 不在快路径。
一、为什么要分快慢两路径
实体每次 dirty 会触发:
| 信号 | 空间索引重建 | 顶点缓冲重构 | 样式缓冲刷新 |
|---|---|---|---|
changed() |
✅ | ✅ | ✅ |
styleChanged() |
❌ | ❌ | ✅ |
只改颜色 / 线宽等样式 → 用 styleChanged() 省掉前两步,差几倍性能。
二、基础用法
mapcadLayer.getEntities()
.filter(e => e.layerId === '标注')
.forEach(e => {
e.color = 0xff0000;
e.styleChanged(); // ← 不是 changed
});
无需手动包批处理:styleChanged 只标脏,重绘由 requestAnimationFrame 自动合并到下一帧。
三、只修改样式的属性白名单
styleChanged() 快路径走 renderCache.updateStyleProps → 实体 updateFeatureStyleProps(feature),只回写以下 feature props:
color(→t.color)lineWidth(→t.line_width,跳过 TEXT_FILL/TEXT_STROKE 角色)——⚠️ 只在lineWidth > 0时写入、从不删除:把线宽改回 0 时缓存里的旧line_width留着,须用changed()effectColor/effectWidth/effectOpacity/effectBlur(→t.effect_*;effectColor===-1时删除这些 props)
以下属性 styleChanged() 不会生效,必须用 changed():
fillColor/fillOpacity/borderOpacity/opacity—— fill/透明度 props 不在回写清单,改了画面不变visible—— 可见性只在全量重建时过滤(!d.visible → continue),styleChanged 后实体仍在渲染桶里layerId—— 图层隐藏检查hiddenLayerChecker只在全量路径执行lineType/ltScale/ltOffset—— 线型改变 tessellation 几何(虚线展开),必须重建- 任何几何(point / center / radius / angle / text ...)、
rotation(影响包围盒) setCustomProperty—— 不影响渲染(也不用 dirty,业务属性随便改)
四、大量实体瞬切主题
function applyTheme(theme) {
mapcadLayer.getEntities().forEach(e => {
e.color = theme[e.layerId] || theme.default;
e.styleChanged();
});
}
applyTheme({ wall: 0x888888, door: 0xff4444, window: 0x44ff44, default: 0xcccccc });
五、按条件批量染色
mapcadLayer.getEntities().forEach(e => {
const temp = e.getCustomProperty('temp')?.value ?? 0; // 返回 {type,value} 包装,取 .value
if (temp > 100) e.color = 0xff0000;
else if (temp > 60) e.color = 0xffaa00;
else if (temp > 30) e.color = 0x00aaff;
else e.color = 0x00ff00;
e.styleChanged();
});
六、事务包装 Undo
改属性/styleChanged() 不会自动记 undo(只有 store.add/store.delete 自动入栈),空事务也不入栈——光把 applyTheme 包进事务,Ctrl+Z 什么都不撤。要可撤销,改之前逐个 recordModify 快照:
const um = mapcadLayer.undoManager;
um.beginTransaction();
mapcadLayer.getEntities().forEach(e => {
um.recordModify(e); // 改之前快照
e.color = darkTheme[e.layerId] || darkTheme.default;
e.styleChanged();
});
um.endTransaction();
这样一次 Ctrl+Z 撤销整批样式修改(撤销是按快照删旧实体再加回,见 drawing/undo-redo)。
七、批量显隐
visible 不在 styleChanged 快路径(见 §3),要用 changed():
mapcadLayer.getEntities()
.filter(e => e.layerId === '辅助')
.forEach(e => { e.visible = false; e.changed(); });
八、特例:批量 deleteEntity
删除要重建空间索引,没快路径;直接循环 deleteEntity 即可(重绘按帧合并),需要一步撤销就包 beginTransaction/endTransaction。
九、常见坑
- 用
changed()改样式 → 慢数倍,几何并没变。 - 改完几何又改颜色:
changed()已含样式刷新,一次即可——千万别在changed()之后同帧再styleChanged():后者把 id 重新标成 style-only,本帧只 patch 缓存 feature 的样式,几何更新被吞(且isDirty被清,之后也不会补)。顺序反过来(先styleChanged后changed)则无害。 - styleChanged 后 bounding box 不变:正确;只有
changed才会刷新空间索引。 - visible/fill 不属于样式快路径:
visible、fillColor、fillOpacity等改了要用changed();styleChanged()只会更新缓存 feature 的 color/line_width/effect_*,其余属性画面不变。 - 实体图层字段是
layerId:不是layer。
相关
- 实体公共样式 → entity/style-props
- 渲染分桶 → perf/render-buckets
- 仅样式快路径 → perf/style-only-fast-path