当前位置: 首页 > Web前端 > HTML5

基于HTMLWebGL的会展中心智能监控系统

时间:2023-04-05 19:10:46 HTML5

前言随着近年来物联网、万物互联等诸多概念的火爆,智慧城市的概念早已为人们所熟知,而作为城市的一部分,智能建筑也是最重要的,智慧园区、智慧社区如雨后春笋般涌现。智慧建筑是指根据用户需求,优化建筑的结构、系统、服务和管理,为用户提供高效、舒适、便捷的人性化建筑环境。智慧楼宇不仅仅是智慧园区,针对智慧社区的模型,我这里通过HTforWeb做了一个以会展中心为主体的智慧楼宇监控系统。实现场景呈现的效果预览代码通过上面的效果预览,可以区分整个监控系统分为三个层次,分别是主体、建筑和展厅。如果使用单个graph3dView加载所有场景,通过dm.clear()清除场景,dm.deserieialize()加载新场景。这种切换方式必然会出现很短的渲染时间,使得切换不连贯,所以我这里使用了3个graph3dView来呈现各自的层级模型,通过notifier事件通知器监听场景切换,代码如下:notifier.add((event)=>{if(event.kind==='sceneChange'){constoldSceneKey=event.oldScene,newSceneKey=event.newScene,oldScene=G[oldSceneKey],newScene=G[newSceneKey];oldScene.removeFromDOM();newScene.addToDOM();if(newScene.graph2d.isAnimed){newScene.graph3d.animByList();}else{newScene.graph3d.animByList(newScene.graph2d.animByList,newScene.graph2d);}}});其中removeFromDOM是一个自封装的方法removeFromDOM(){constg3d=this.g3d,view=g3d.getView();如果(查看。删除){查看。删除()}否则{视图。父节点。removeChild(view)}这个。通知者。火({种类:'重置',});}但是还是有问题。如果页面默认没有放置graph3dView,则不会请求和渲染场景中的obj等模型相关资源。这样对性能很友好,但是当我第一次切换场景的时候,还是会有很短的请求和渲染时间,所以这里需要预加载资源资源预加载这里我在body中添加了一个与窗口同宽高的未显示的div元素,将当前未显示的graph3dView放入其中触发相应obj的请求和渲染等模型资源完成预加载。代码如下:constpreloadDiv=document.createElement('div');preloadDiv.style.position='absolute';preloadDiv.style.bottom='100%';preloadDiv.style.width='100%';preloadDiv.style.height='100%';document.body.appendChild(preloadDiv);scene2.addToDOM(preloadDiv);scene3.addToDOM(preloadDiv);模型加载完成后执行动画。obj等资源文件有一定的大小,不同带宽和网速的用户加载时间可能不同。这里需要判断obj是否加载满,加载完成后再进行动画效果。通过ht。Default.handleModelLoaded监控是否请求加载所有模型。加载完成后执行动画,顺便释放之前预加载的graph3dView。代码如下:letmodelSize=0;ht.Default.handleModelLoaded=(name,model)=>{modelSize++;如果(modelSize===62){scene1.graph3d.enableShadow();scene3.graph3d.enableShadow();scene2.removeFromDOM();scene3.removeFromDOM();scene1.graph3d.animByList(scene1.graph2d.animByList,scene1.graph2d);}};动画按照参数的顺序执行。我希望第一次加载场景时,视角放大后左右面板会多一点。加载后动画效果是按照不完整的线性顺序执行的,所以我通过ht.Default.startAnim方法通过参数数组封装了一套动画方法。代码如下:animByList(callback,obj){this.isAnimed=true;constanimList=this.animList,self=this;让callAnim=(ind)=>{constparam=animList.get(ind);param&&self.anim(param,()=>{callAnim(ind+1);constlastParam=animList.get(ind+1);lastParam||callback&&callback.call(obj||this);});};callAnim(0);}anim(animParam,callback){constself=this,time=animParam['time']||1000,缓动=animParam['缓动']||函数(t){返回t*t;},func=animParam['func'];this.__animObj=ht.Default.startAnim({duration:time||1000,easing:easing,action:function(v,t){constV=v,T=t;functionanimFunc(param){让v=V,t=T;if(paraminstanceofFunction){param(v,t);}else{consttype=param['type'],object=param['object'],objectTag=param['objectTag'],key=param['key'],oldValue=param['oldValue'],newValue=param['newValue'],oneTime=param['time'],scope=param['scope'];如果(范围){v=v<范围[0]?0:v>作用域[1]?1:(v-作用域[0])/(作用域[1]-作用域[0]);}else{v=!oneTime||一次>一次?v:v*time/oneTime<1?v*时间/一次时间:1;}让对象,值;对象=对象?对象:对象标签?self.view.dm().getDataByTag(objectTag):undefi内德;如果(!obj)返回;如果(!isSameType(oldValue,newValue)||!isNumORNumArray(oldValue))返回;if(oldValueinstanceofArray){if(oldValue.length!==newValue.length)返回;constdarr=newValue.map((n,i)=>{returnn-oldValue[i];});value=oldValue.map((n,i)=>{returnn+darr[i]*v;});}else{constd=newValue-oldValue;值=旧值+d*v;}ht.Default.setPropertyValue(obj,type,key,value);}}if(animParaminstanceofArray){animParam.forEach(ele=>{animFunc(ele);});}别的{动画函数(动画参数);}},finishFunc:函数(){func&&func(func);回调&&回调();},});}参数格式如下://Cameramovementparam={object:g3d,type:undefined,key:'eye',oldValue:[-118,5130,15858],newValue:[-26,1130,3494],time:1000,}animList.add();//标题从左到右出现param={object:title,type:'style',key:'clip.percentage',oldValue:0,newValue:1,time:1500,};animList.add(param);可点击部分的高亮效果可以高亮对于被点击的部分,我添加了高亮效果,设置鼠标悬停高亮模式,通过g3d.getHighlightHelper().setFetchTargetFunc过滤需要鼠标高亮的图元。代码如下:g3d.setHighlightMode('mouseover');g3d.getHighlightHelper().setFetchTargetFunc(function(nodes){letsortList=newht.List(nodes);returnsortList.toArray(node=>{返回jumpList.contains(node);});});楼层透视跳转因为整体楼层比较大,每层可选择的展区比较小,所以这里我做了视角调整。可以使用flyTo将视角移动到对应楼层的视角。除了使用右侧边栏选择和移动,还做了鼠标移动到对应楼层右键改变视角的处理,使用新建的类messageView用于交互式提示g3d.flyTo(floor,{animation:true,direction:[0,1,2],center:floor.p3().map((n,i)=>{returni!==1?n:n+floor.getTall()/2;}),距离:distances[newFloor-1],});总结随着科技的快速发展,智慧建筑将如雨后春笋般涌现,其应用场景也将不断扩大,应运而生的数据可视化管理系统也应升级,将数字信息转化为以数据为代表的直观信息图形和图像信息,可以清楚地展示在客户面前。这将是一个不可阻挡的时代趋势。还有更多的可视化案例可以参考:https://www.hightopo.com/demo...