mapdata-hider
本文回答:
createMapDataHider/MapEntityHider—— 把 DWG 原图里的实体"用样式隐藏",避免 SDK 接管后双重显示;栅格 / 矢量底图双模式。
一、为什么需要
查出实体 → 加动画 → 但原图还在 → 画面上有两份 → 需要隐藏原图那份。
但不是 "删除",是"样式级隐藏",可逆,也不影响底图其它内容。
二、创建
const hider = mapcadLayer.createMapDataHider();
// 等价 new vjmapext.MapEntityHider(map)
它会自动识别当前底图模式:
| 底图 | 机制 |
|---|---|
栅格(svc.rasterStyle()) |
`map.updateStyle(svc, { expression: "if(gInObjectId in 'id1 |
矢量(svc.vectorStyle()) |
map.setFilterEx(layers, ['!', ['match', ['id'], ids, true, false]]),前端过滤 |
三、核心 API
type HideItem =
| string // 栅格 objectid
| number // 矢量 feature.id
| { id?, objectid? }
| GeoJSON.Feature; // 推荐,两种 id 自动抽取
hider.hide(items): Promise<void>
hider.show(items): Promise<void>
hider.clear(): Promise<void>
hider.getHiddenIds(): string[] // 栅格 objectid
hider.getHiddenFeatureIds(): number[] // 矢量 feature.id
hider.isHidden(id): boolean
hider.refresh(): Promise<void>
hider.mode: 'raster' | 'vector'
四、基本使用
// 1. 查
const fc = await mapcadLayer.queryMapEntities({ entTypes: ['AcDbText'] });
// 2. 隐藏(直接传 Feature,兼容两种底图)
const hider = mapcadLayer.createMapDataHider();
await hider.hide(fc.features);
// 3. 用 SDK 实体重绘
mapcadLayer.featuresToEntities(fc).forEach(e => mapcadLayer.addEntity(e));
// 4. 恢复原图
await hider.clear();
五、栅格 vs 矢量的关键差异
| 模式 | 过滤字段 | 类型 | 来源 |
|---|---|---|---|
| 栅格 | gInObjectId |
字符串 '9BE_2' |
feature.properties.objectid |
| 矢量 | ['id'] |
数字 1234 |
feature.id(DB 主键) |
警告:只传 objectid 数组给 hide():
- 栅格下生效
- 矢量下命中不到(
['match', ['id'], ['9BE_2'], ...]永远 false)→ 看起来"没效果"
解决:传 Feature 对象,两种 id 都带着。
六、多个 hider 独立管理
const textHider = mapcadLayer.createMapDataHider();
const roadHider = mapcadLayer.createMapDataHider();
await textHider.hide(textFeatures);
await roadHider.hide(roadFeatures);
// 导出时分别传:
await mapcadLayer.exportDwg({ hider: textHider }); // 只删文字
await mapcadLayer.exportDwg({ hider: roadHider }); // 只删道路
注意:多 hider 是"后写覆盖"不是合并。栅格模式下所有 hider 默认写同一个 styleName(myCustomStyle_temp)的样式,矢量模式下 setFilterEx 也是整体替换——最后一次 refresh() 生效,之前 hider 的隐藏会被顶掉。要并存请给每个 hider 传不同 styleName(栅格)或干脆只用一个 hider 管理所有隐藏 id。
七、配合 exportDwg(导出时删除)
await mapcadLayer.exportDwg({ hider }); // 自动删除源图中被 hider 隐藏的实体
await mapcadLayer.exportDwg({ hider, deleteFromSource: false }); // 仅导出,不删源
见 backend/export-dwg 的 deleteObjectIds / onBeforeUpdate 钩子。
八、栅格底图耗时
栅格模式下 hide 会触发后端瓦片重拉(瓦片里少了被隐藏的实体),通常 300 ~ 800 ms;期间画面会有一次闪。
想避免闪烁:
const canvas = map.getCanvas();
canvas.style.opacity = 0.3;
await hider.hide(fc.features);
canvas.style.opacity = 1;
九、矢量底图瞬时
矢量模式是前端 filter 表达式,1 万 id 内基本瞬时;更大量级(10+ 万 id)时 filter 本身可能慢。
超大量级时可考虑:
- 分组 hide:一次 1 万
- 改用 CSS opacity 方案
- 用 feature-state + 样式表达式把实体变透明:
fc.features.forEach(f => map.setFeatureState({ source: 'vec', id: f.id }, { hidden: true }));
// layer 样式里:
// lineOpacity: ['case', ['boolean', ['feature-state', 'hidden'], false], 0, 1]
十、常见坑
- 只传 objectid → 矢量不生效:务必传 Feature 对象。
- 栅格模式 hide 后画面闪一下:瓦片重拉;上面 opacity 技巧或用矢量底图。
- 连续 hide 多次:每次都会触发样式刷新;收集好 features 再一次 hide。
- hider 丢失引用:GC 后无法 clear;用全局 Map 持有。
- 导出时忘了 hider:导出的 DWG 里既有原实体又有 SDK 实体 → 双份。
相关
- 查询 → mapdata-query
- 转实体 → features-to-entities
- 导出 → backend/export-dwg