三维 / 组态 / 地图场景配方与联动模板
返回 SKILL.md。硬门禁:piece 选项名一个都不许猜——一律查本技能
references/widgets/下的 scene-3d.md / scada-2d.md / map-2d.md(终极权威 widget-schema.generated.json)。本文只给"组合套路",不是选项字典。
0. 通用:builder 组件经 addWidget 一次建成
ctx.addWidget / screen.addWidget 入参支持顶层 pieces(SDK BuildPieceNodeInput,自动补 uid):
await screen.addWidget({
type: 'scene-3d', uid: TWIN_UID, position: [24, 152], size: [1520, 904],
options: {
'geometry-unit': 'percent',
'scene3d-initialized': true, // scada 是 'scada-initialized'(防播种演示内容)
'point-key-field': [f('conn_pts', 'tbl_pts', '键')],
'point-value-field': [f('conn_pts', 'tbl_pts', '值')],
interactions: twinInteractions(),
},
pieces: twinPieces(),
})
场景定义放 scenes/*.ts:导出 XXX_UID 常量 + xxxPieces() + xxxInteractions(),联动目标(设备→piece uid)集中成映射表。
1. scene-3d 配方(数字孪生)
- 固定开头:单例
{ uid:'scene3d-scene', type:'scene3d-scene' }+{ uid:'scene3d-camera', type:'scene3d-camera' }(uid 逐字固定);灯光 ambient + directional(cast-shadow);地面 plane(pickable:false)。 - 零素材离线纪律:背景用
bg-mode:'sky'程序化天空;不用外链模型/瓦片/在线粒子预设;粒子只用内置fx-kind: fire/smoke/rain/snow/firework/text。 - 常用组合:楼宇/装置=
scene3d-extrude(edges 科技棱线,flow-gradient 光效档);罐=scene3d-tank(液位测点);管道=scene3d-pipe(flow +flow-rules按值启停);周界=scene3d-wall(state-rules 变红 + blink);区域=scene3d-zone;巡检=scene3d-trail+ 形状path-points路径动画;点位批量=scene3d-sprites/scene3d-points;人员定位=scene3d-persons(sprite 档离线安全,data-key测点值 JSON[[id,x,y,z,名],…]差分平滑移动);标注=scene3d-label/scene3d-board/scene3d-fxmarker/scene3d-beam;书签=scene3d-view;后期=scene3d-effects(bloom +outline-hover+hover-tip,每场景一份)。 - 测点驱动:画板绑长表键/值两列;元素
data-key+state-rules(值=颜色每行一条)/blink-values/flow-rules;热力/人员/点云的data-key值为 JSON 串整批刷新。 - 运行时增删 piece:
scene.addPiece({ type:'scene3d-tank', uid, options })/scene.removePiece(uid)(builder 通用句柄;禁止删scene3d-scene/scene3d-camera)。不要只改raw.node.pieces。 - 演练显隐:火焰/烟雾粒子平时
enabled:false或藏于状态,演练时用交互动作scene3dSetVisible(经 receiveBehaviorEvent 触发)或直接改测点驱动的元素状态。
2. scada-2d 配方(工艺组态)
- 画板 options:
scene-width/height与摆放尺寸 1:1、theme:'tech-blue'、appearance-3d:true、'scada-initialized': true、绑长表键/值。 - 图元 node:
shape从 159 种里选(泵 pump/阀 valve·motor-valve/罐 tank·sphere-tank/水箱 water-tank/立式换热器 shell-tube-exchanger/深井泵 deep-well-pump/污泥泵 sludge-pump/絮凝池 floc-tank/配水井 distribution-well/冷却塔/传感器 sensor·pressure-sensor/声光 beacon/数码屏 digital-display/仪表 gauge/温度计/流量计/火炬 flare-stack/标题栏 title-bar/状态牌 status-pill…);几何用geo-x/y/w/h场景坐标;fill/stroke留空跟随主题。 - 按值驱动(全在
data-enabled:true下):state-by-value+state-rules状态色;anim-by-value+anim-rules(1=spin:1.6 / 0=none / 2=shake——泵按值起转、故障抖动);液面/仪表类形状配value-min/max量程自动画液位/指针,show-value-text出读数;fill-by-value阈值三段色(气体检测器标配)。 - 连线 link:
from-node+from-port/to-node+to-port(通用四边 n/e/s/w)+waypoints途径点;主工艺管用line-style:'pipe'(线宽即管径 10~16)+flow:true;按值流动data-enabled + data-key + flow-by-value + flow-rules(1=on:1.6\n0=off)——泵停管路停流(含路径动画符号)的联动就靠它。 - 布局纪律:先在注释里排版面坐标(回路走向、途径点避让图元),连线端点引用写完必跑一致性单测。
- 图元点击:代码侧
ctx.getScada(uid).onNodeClick(payload => ...)(开趋势窗等)。
3. map-2d 配方(GIS 一张图)
- pieces 三段式:
map-body(单例、uid:'map-body'、放第一个)→map-source-*(可选)→ 图层map-*(数组顺序=叠放)。 - 地理模式(map-body 的 options,不是 map-2d 本体的):
coordinate-system:'geographic'+basemap:'gaode-vec'(需联网;离线降级为暗底不炸)+map-center/map-zoom。 - 企业/设施点位:
map-symbol或map-circle,data-input:'bind-fields'直接绑台账表marker-lng/lat/name/value;按属性变色用map-circle/map-geojson的数据驱动样式:point-color-mode:'field'+point-color-field+point-color-stops(每行输入 => 颜色,风险四色标配——map-symbol是symbol-label-color-mode/field/stops组,具体键名查 map-2d.md §6.3-C/widget-schema)。 - 风险四色区域:
map-source-geojson(内联 FeatureCollection,属性带 name/level)+map-polygon/map-geojson引用源(data-input:'source'+data-source-uid: [{ refType:'element', targetPath:['源uid'] }]),填充色按属性 stops。 - 告警特效:
map-fx-pulse-ring(告警企业脉冲)/map-fx-fire(事故火点)绑一张"告警点位表"(sim 推行,空行=无特效)——特效层同享 §6.3 数据来源。 - 悬停/点击:图层
tooltip-enable+tooltip-fields;交互写在 map-2d 自身options.interactions(marker-clickpayload=要素属性行);代码侧句柄ctx.getMap(uid)→flyTo/fitData/setZoom(列表点行定位标配)。 - 控件:map-body 内置
control-zoom/control-scale/control-compass等四角控件选项,或独立map-control-legend/map-control-view组件(target-map留空=本页第一张图)。
4. 交互持久化模板(version 2)
function ix(trigger: { name: string; options?: Record<string, unknown> }, action: { name: string; options: Record<string, unknown> }, alias: string) {
const trig = { name: trigger.name, options: trigger.options ?? {} }
return { trigger: trig, interactions: [{ alias, enable: true, trigger: trig, action: { name: action.name, options: { start: 'meanwhile', delay: 0, duration: 1, ...action.options } } }] }
}
// options.interactions = { version: 2, groups: [ ix(...), ... ] }
常用分组(scene-3d):
| 触发 | 动作 | 效果 |
|---|---|---|
scene3d-piece-click |
scene3dPopup { mode:'open', 'piece-uid':'' } |
点谁弹谁 |
scene3d-piece-dblclick |
scene3dFocus { 'piece-uid':'', padding, 'fly-transition':true } |
双击聚焦 |
receiveBehaviorEvent { eventName:'twin-focus' } |
scene3dFocus { 'piece-uid':'' }(留空取 payload.pieceUid) |
跨页告警定位 |
receiveBehaviorEvent { eventName:'twin-overview' } |
scene3dFlyTo { 'view-uid':'v_overview' } |
回总览书签 |
5. 跨页联动配方(代码侧)
- 告警 → 三维定位:
ctx.setActiveScreen('pg_twin')+setTimeout(() => ctx.emit('twin-focus', { pieceUid }, TWIN_UID), 400)(切页动画留时)。 - 告警/列表 → 地图定位:
ctx.setActiveScreen('pg_map')+ctx.getMap(MAP_UID)?.flyTo(...)。 - 表格点行 → 详情窗:
table.onSelect(sel => { 刷写窗内 uid 组件 setOption; ctx.openWindow('win_x', { keepPosition: true }) })(sel是选中维度{别名:值}非整行,整行用table.getValue().row,见 scaffold.md §4)。 - 演练副作用(自动开应急窗/切页)由 sim runtime 的事件回调执行,不进纯函数。