搞数字孪生可视化项目,特别是厂区、园区、城市级别的场景,最容易被客户问倒的问题往往不是大屏漂不漂亮,而是“我场景里挂了几百个设备标记,怎么快速找到某一个?”
设备一多,靠鼠标在三维场景里拖、转、放大找点位,不仅效率低,实际演示时还显得特别外行。所以我一直觉得,搜索框虽然是个小交互,但它直接决定了这套数字孪生系统在真实工作流里能不能用起来。
这篇我以山海鲸可视化为例,完整拆解一个实战需求:在数字孪生场景里做一个搜索框,输入设备名称或编号,自动匹配并定位到对应的标记点。整个过程从设计思路、数据准备、事件配置到真机调试的坑,都会讲到。
适合谁看?正在做数字孪生可视化项目、想给大屏加搜索定位功能但不知道从哪下手的人,尤其是用了山海鲸这种零代码/低代码平台、想摆脱纯展示型大屏的朋友。
1. 整体设计思路:为什么搜索框是数字孪生场景的刚需
1.1 在几十上百个设备里找一个点位,为什么这么难
先说说痛点。很多人第一次做数字孪生项目时,觉得把设备模型、管线路由、监控数据都摆到场景里就完事了。结果演示的时候,领导突然问一句:“三号车间的二号冷水机组现在什么温度?”
现场瞬间安静。因为那个点位在三维场景里藏在建筑模型后面,你一边拖视角一边回忆“我记得好像在东边那块区域”,转了两圈还没找到,场面非常尴尬。
这背后是一个很现实的问题:数字孪生场景是三维的、连续的、信息密集的,但人的导航能力在虚拟空间里是有限的。别说几百个标记点,超过三十个,纯靠肉眼找就已经开始费劲了。更别说点位上还有设备状态、告警信息、实时数据这些附加内容,信息越密集,定位越困难。
所以搜索框解决的不是“炫不炫”的问题,而是“这系统能不能用”的问题。它把用户从“三维空间漫游”切换到了“按名称精确索引”的思维模式。就像你在一个商场里找一家店,你可以看楼层导览图慢慢找,也可以直接问服务台,搜索框就是这个服务台。
1.2 搜索框查询的本质:名称匹配 + 空间定位 + 信息展示
把搜索框这个需求拆开看,其实它包含三个动作:
第一个动作是名称匹配。用户输入关键词,系统在点位数据源里做模糊匹配或者精确匹配,找到符合条件的标记点。这里有个细节,匹配的字段不只是名称,还有编号、所属区域、设备类型等等,多字段匹配的命中率远比单字段高。
第二个动作是空间定位。匹配到结果之后,系统要控制场景相机移动到目标点所在的位置,并且把视角对准它。这一步如果做得生硬,体验会非常差。好一点的做法是相机平滑飞行,目标点自动居中,标记点高亮闪烁,让用户一眼就知道“找到了”。
第三个动作是信息展示。定位之后,通常还要弹出这个设备的属性面板或者数据面板,展示当前状态、实时数值、历史曲线入口等信息。这样搜索就不是单纯“找到图标”,而是“找到并把相关数据带出来”,这才是数字孪生场景里搜索框完整的使用闭环。
1.3 为什么用山海鲸可视化来实现这个功能
山海鲸可视化是我在项目里经常用的一款零代码数字孪生开发工具,它有自己的场景编辑器、数据组件和交互事件机制,比较适合我这种需要快速交付项目、又不想从底层写Three.js或Cesium的团队。
它的核心优势在于三个方面:一是数据接入比较省事,支持MySql、API、Excel、WebSocket等常用数据源,点位数据可以直接从业务系统同步过来;二是有完整的交互事件配置能力,敲好数据表达式,点击、输入、筛选、场景联动这些动作都能绑定起来,不需要像Three.js那样自己管理渲染循环;三是它内置了三维场景的相机控制接口,通过组件和脚本触发场景视角切换可以实现平滑的定位效果。
所以下面这套实现方案,整体思路基于山海鲸的组件化交互机制,如果你用的是其他数字孪生平台,原理也可以平移套用。
2. 核心概念拆解:数据组件、标记点与相机视角
2.1 标记点数据从哪里来、长什么样
在做搜索之前,先把标记点数据的底子打好。山海鲸可视化里的标记点,本质上是一组绑定了空间坐标和属性信息的数据记录。每条记录除了名称,还应该有经纬度坐标(或三维模型坐标)、所属系统、设备编码、运行状态、关联数据等字段。
举个例子,一个制冷站监控系统的点位表大概长这样:
| 设备名称 | 设备编号 | 所属系统 | 经度 | 纬度 | 高度 | 状态 |
|---|---|---|---|---|---|---|
| 一号冷水机组 | CH-01 | 制冷系统 | 120.1536 | 30.2893 | 5 | 运行 |
| 二号冷水机组 | CH-02 | 制冷系统 | 120.1537 | 30.2894 | 5 | 停机 |
| 冷却塔A | CT-A | 冷却水系统 | 120.1538 | 30.2892 | 12 | 运行 |
注意,这里的坐标字段很关键,搜索定位本质上就是根据这条记录里绑定的坐标去驱动相机。如果点位是贴在地图上的,用经纬度;如果点位是挂在BIM模型上的,用模型局部坐标。做数据表的时候就把坐标字段准备好,后面能省很多事。
2.2 搜索框的本质:一个带查询能力的交互控件
你可能会觉得搜索框不就是输入文字嘛,但在数字孪生平台里,搜索框是一个“可以触发数据过滤和事件流转”的控件。它本身不存数据,它只是接收用户输入,然后把输入内容作为查询条件,传给数据源做匹配,最后把匹配结果分发到场景和列表组件。
这就好比你去图书馆查书,你在一台检索机上输入书名,检索机把请求发给后台的图书数据库,数据库把匹配结果返回,检索机再把结果显示在屏幕上。搜索框就是那台检索机,数据源是图书馆的数据库。
在山海鲸里配置搜索逻辑时,需要在搜索框的“值改变”、输入事件或者按钮点击里绑定一个查询动作,把输入内容写成一个筛选条件,目标是对应标记点数据源做过滤,得到的结果再驱动场景相机和列表展示。
2.3 视角定位原理:从“坐标查找”到“相机飞行”
搜索定位最后落地的动作,是让三维场景里的相机飞到目标点上。理解这个机制,可以类比成你在地图App里搜索一个地址,App会先把地图的中心平移到那个位置,再放缩到合适的层级,必要的时候还会给你弹一个气泡卡片。
山海鲸的场景编辑器和运行时,同样有相机控制的能力。最简单的做法是通过脚本或内置动作,传入一个目标坐标和视角参数,系统自动计算相机的移动路径和朝向,做平滑过渡。如果目标是一个设备的标记点,理想的效果是:相机从当前位置沿着一条弧形轨迹飞过去,落点后设备标记正对镜头,并且标记点高亮闪烁,旁边弹出属性卡片。
这里有个细节,很多初学者会忽略:视角参数不只是“坐标”,还包括“朝向”“俯仰角”“视野范围”。如果只传坐标不传视角,相机虽然飞过去了,但可能是从侧面或者背面看设备,标记点被设备模型自身挡住,体验就很差。所以配置定位动作时,一定要同时把相机朝向设备的水平角和俯仰角带上,必要时还得调整远近裁剪面,避免离得太近把标记信息截掉。
3. 完整实操:在山海鲸里实现搜索框查询标记点
3.1 第一步:建好点位数据源并接入项目
先打开山海鲸场景编辑器,在左侧的数据面板里新建一个数据表格组件,用来存点位信息。我一般建议把点位数据单独放到一个表格里,设备名称、设备编号、所属系统、经纬度或模型坐标、状态这些字段一次建好。
然后把数据接进来,山海鲸支持两种方式:
- 静态数据:适用于点位固定、不频繁变动的场景,直接把上面的表格填进去就行。
- 动态数据:适用于点位信息来自业务数据库的场景,用数据集或API接口绑定,确保设备新增时,搜索也能动态覆盖。
实际操作中,我多半先用静态数据把功能跑通,确认搜索、定位、弹窗联动都没有问题以后,再切换到正式数据库。这样排查问题时不会被数据同步的故障干扰。
3.2 第二步:搭建搜索面板与结果列表
在山海鲸画布上新建一个搜索面板,里面放一个文本输入框、一个搜索按钮,再放一个列表组件用来展示搜索结果。
这个面板建议固定在屏幕的左上角或右下角,不要遮挡场景中心区。如果你做的是大屏项目,搜索面板通常放在两侧数据栏的顶部,这样既留出视线区域给三维场景,又方便操作。
列表组件用来展示所有匹配到的标记点,每一行显示设备名称和设备编号即可,也可以附带所属系统或状态。配置项里注意开启“点击行触发事件”,这样后面才能做“点击搜索结果 -> 定位到标记点”的联动。
3.3 第三步:配置搜索规则与匹配逻辑
这是比较核心的一步,也是很多零代码用户最容易卡住的地方。
在山海鲸里,搜索逻辑一般通过“数据筛选”动作或者“条件查询”表达式实现。我在实际项目中的做法是:在搜索按钮的事件里绑定一个数据过滤动作,过滤条件是“当设备名称包含输入框文字 或 设备编号包含输入框文字 或 所属系统包含输入框文字时,把数据传给结果列表”。
这里要注意“包含”和“等于”的区别。搜索一般都要求模糊匹配,你输一个“冷”字,能匹配到“一号冷水机组”,也能匹配到“冷冻水泵”,而不是必须输完整名称才出结果。这种做法更符合真实使用习惯。
我习惯把匹配条件写成多字段并行,类似下面这种逻辑,如果你在平台里可以写表达式,可以参考这个思路:
// 伪代码:多字段模糊匹配搜索 let keyword = searchInput.text.trim(); let filtered = deviceList.filter(item => { return item.name.includes(keyword) || item.code.includes(keyword) || item.system.includes(keyword); }); resultList.data = filtered;如果你平台里支持表达式,其实就是在一条过滤条件里,把“名称包含keyword”和“编号包含keyword”“系统包含keyword”用或连接起来。至少做三到四个常用字段的匹配,用户的体验会有很明显的区别。
如果你的需求是支持拼音首字母,或者模糊搜索同音词,那需要数据源里提前存一个拼音字段或首字母字段,搜索时匹配它。做不做这个功能,取决于客户的输入习惯,有些厂里的老师傅是不会打全拼的,这个可以后续优化。
3.4 第四步:实现结果点击与标记点定位联动
搜索出来的结果只是一个列表,它要和三维场景打通,才算完成了整个交互闭环。
在山海鲸里,给列表的每行绑定一个“点击事件”,当用户点击某一行时,把这一行对应的点位坐标、设备名称、状态参数提取出来,传给场景相机执行定位动作。
定位动作的核心是调用场景的“视角切换”或“飞向目标”能力,传入目标点的坐标。如果你不希望用户看到相机穿模的瞬间,可以把过渡曲线设置为缓动,飞行时间控制在0.8到1.5秒之间,太短了会晕,太长了显得拖沓,1秒左右是比较舒服的节奏。
定位完成后,同时触发这个标记点的高亮显示和属性弹窗。在山海鲸里可以给标记点挂一个“选中态”样式,比如发光、放大、变色,再弹出一个数据卡片,展示当前设备的实时参数。
如果搜索结果是多个匹配,点击列表里的每一行,都应该能定位到对应点位。这里有个配置细节:行点击事件里绑定的数据对象必须是“当前行”,不要绑成“整个结果集”,否则不管点哪一行,它定位到的都是第一个点或者最后一个点,这是一个非常经典的错误。
3.5 第五步:处理空结果、高亮恢复与体验细节
功能主线跑通以后,还有一些体验细节决定系统的“高级感”。
第一个是空结果提示。搜索没有匹配项时,不能一片空白,要在结果列表里展示“未找到相关设备”的提示,同时场景不做任何定位动作,保持原视角。
第二个是重复搜索的处理。用户先搜了“冷水”,定位到了一号冷水机组,接着又搜“冷却塔”,这时场景要把上一次的高亮标记恢复成普通状态,再定位到新的目标。如果上一个标记点一直保持高亮状态,后来的定位会被视觉干扰。
第三个是搜索按钮和回车键的响应。很多用户在搜索框里输入完喜欢按回车,所以除了给按钮绑定事件外,也要给输入框绑定“回车”事件,触发同一个搜索动作。
第四个是结果数量限制。如果匹配项太多,比如搜一个“泵”字,出来几十条,列表会被撑得很长。建议限制显示前10条或前20条,并提示“共N条结果,请缩小关键词范围”,避免列表组件因为数据量过大出现渲染卡顿。
4. 常见问题与排查技巧实录
4.1 中文输入法导致“回车直接上屏”问题
在搜索框里输入中文时,很多人会遇到一个问题:用输入法打完了拼音,按回车想触发搜索,结果回车被输入法截胡,直接把拼音上屏到输入框里了,搜索根本没触发。
这在山海鲸里非常容易出现,因为输入框的“值改变”事件在输入法组合阶段也会触发,导致过滤逻辑在拼音状态下就跑了一遍。排查时你可能会发现,搜索结果时而对时而不对。
我的解决办法是:搜索动作不绑定在“值改变”事件上,而是绑定到搜索按钮点击或者输入框的“提交/搜索”事件上。这样用户输入完,点一下按钮或者按输入法“搜索”键,事件才会触发,避免了输入过程中的误触发。同时配置输入框的下拉候选或即时搜索时,务必用防抖逻辑,具体做法是等用户停顿300到500毫秒后再执行搜索,而不是每个字符都去过滤,否则数据量一大,结果列表会频繁刷新,视觉上一直闪烁。
4.2 关键词带空格或大小写导致匹配失败
有一个很隐蔽的坑:用户从Excel复制设备编号时,可能会带上前后的空格,比如“CH-01”变成了“ CH-01”,搜索结果就匹配不上了。因为过滤条件做的是严格包含,空格也是字符的一部分。
处理方式是在搜索前把输入关键字做一次trim(去掉首尾空格),同时对数据源里的编号字段也做一次去除空格的归一化。另外,设备编号里的英文字母大小写,建议在匹配时统一转为小写或大写再比较,否则用户输入小写“ch-01”匹配不到“CH-01”。
这段逻辑用伪代码表达大概是这样,你平台里如果支持表达式,就按这个思路转换:
let keyword = searchInput.text.trim().toLowerCase(); let filtered = deviceList.filter(item => { let code = (item.code || '').trim().toLowerCase(); let name = (item.name || '').trim().toLowerCase(); return name.includes(keyword) || code.includes(keyword); });4.3 相机定位过去发现视角不对,标记被模型挡住
定位成功后,相机虽然飞到了目标位置附近,但标记点可能处在建筑模型背面,或者视角角度特别诡异,根本看不到。这个问题的根因是定位动作里只传了坐标,没有配置好观察视角。
在山海鲸的视角切换事件里,通常可以设置相机位置坐标、目标点坐标(也就是看向哪里)、以及视野角度。我的做法是:目标点不取设备本身的中心,而是取设备标记点上方1.5到2米的一个点,这样相机会稍微俯视,标记点正好出现在画面中心偏下一点,弹窗也不会遮住设备模型。
如果标记点在楼层内部,做了剖切或楼层透明,要额外确认定位视角所在层有没有开启对应楼层的显隐控制,否则相机飞到那儿,看到的还是一堵墙。
4.4 搜索框与结果列表数据不同步
有时候会出现搜索框里已经输入了新的文字,但结果列表还是上一次的旧数据。排查思路是先看数据过滤事件有没有正确传递参数,再看结果列表有没有配置自动刷新。
在山海鲸里,如果结果列表绑定的数据是静态的,过滤动作只会改输入框的值,列表不会自动更新。正确的做法是,搜索事件里同时做两件事:给列表赋值过滤后的数据、清空输入框的值(或保留关键字但重置数据源)。如果你发现改了数据源但列表没反应,检查一下列表组件是否勾选了“跟随数据源自动更新”。
4.5 搜索结果定位后标记点高亮被重置
定位成功后,标记点高亮可能只亮了一秒就被场景刷新重置了,或者切走视角再切回来高亮状态丢失。这个问题的核心是“高亮状态没有被持久化”。
处理方式是把当前选中的设备编号记录到一个全局变量,比如“当前选中设备”的值设为这个编号,然后让标记点的选中样式与“当前选中设备”做条件绑定。这样不管视角怎么切,只要选中编号不变,标记点就一直保持高亮。同时,每次搜索定位时,把上一轮的选中编号清掉或覆盖,就不会出现多个设备同时高亮的问题。
5. 顺带聊聊:数字孪生和MES的边界,到底在哪里
搜索框这个功能做完以后,在项目汇报时我们经常遇到一个追问:“我们厂里已经有MES系统了,所有设备数据都在MES里能查到,你这个数字孪生平台做出来,和MES有什么区别?感觉不如MES管用。”
这句话,做数字孪生的人都听过。“数字孪生不如MES管用”,表面看是功能重叠的质疑,但它背后其实讲的是数字孪生和业务系统各自的定位问题。MES解决的是“生产执行层的数据管理”,比如工单派发、物料跟踪、过程记录、质量追溯;而数字孪生可视化平台解决的是“把系统和设备的位置、状态在三维空间里直观呈现”。
搜索框查询标记点就是两者的一个结合点。MES里查一台设备的状态,查出来的是表格;数字孪生里查一台设备的状态,查出来的是“它在哪、周围是什么、当前什么状态、关联了哪些数据”。前者是数据逻辑,后者是空间逻辑。对一个车间主任来说,看到表格里的“CH-02停机”和看到三维场景里二车间角落那台贴着红色告警标签的冷水机组,判断速度和决策准确度是完全不同的。
所以我的实践经验是,做数字孪生项目时不要试图替代MES,而是要把MES的数据接过来,用三维场景放大数据的可感知性。搜索结果列表里那些编号、状态、报警信息,本质上都是从MES或者设备管理系统里来的,数字孪生平台是它的一个“可视化前端”。把这个定位想清楚,你和客户聊需求时会顺畅很多。
6. 升级方向与经验体会
功能跑通之后,如果你还有余力,我建议在基础搜索之上做两个升级,对项目的最终呈现效果提升非常明显。
一个是“名首拼搜索”。厂里很多老员工计算机操作不熟练,你让他们打全拼“lengshuijizu”,他们宁可翻场景找。但如果支持输入“lsjz”就能匹配到“冷水机组”,这个搜索框的实用价值会高一个档次。做法很简单,在点位表里加一个字段,存设备名称的拼音首字母,搜索时在这个字段上做模糊匹配即可。
另一个是“按区域/楼层过滤”。搜索框旁边加一个下拉筛选,可以按系统或楼层先过滤一遍,再输入关键词搜索。比如用户先选“制冷系统”,再搜“机组”,命中的就是制冷系统内所有机组,结果更精准,而且候选结果的定位也不会出现跨楼层的大范围视角跳转。
最后分享一个我个人的经验,每次做完搜索功能,我都会用一个最简单的方法验收:让一个从没看过这个项目的人来操作,让他找三个指定的设备点位,看他要几步才能找到。如果超过15秒还没找到,说明交互设计还不够顺畅,回头优化,不要自己觉得能用就交付了。搜索框好不好用,不是看功能做没做,而是看一个陌生用户第一次用能不能自己学会。这个标准,比任何技术指标都实用。