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

基于HTML5WebGL的智慧城市模拟

时间:2023-04-05 20:51:42 HTML5

前言智慧城市是一个系统。又称网络城、数字城、信息城。智慧城市建设是一项系统工程:首先要实现城市管理的智能化,智慧城管系统辅助城市的管理。通过管理系统,人们可以监控城市的运行,了解城市每天发生的变化,并及时应对这些变化。进行相应的管理;二是基础设施的智能化,包括智能交通、智能电力、智能安防。交通是城市的驱动力。了解交通情况并加以处理;智慧城市还包括智慧医疗、智慧家居、智慧教育等社会智能,以及智慧企业、智慧银行、智慧门店等智能化生产,全面提升城市生产、管理、运营的现代化水平。等级。本demo采用HTforWeb产品的轻量级HTML5/WebGL建模方案,构建城市建筑场景,添加城市道路,实现智慧城市的Web可视化,通过动画模拟城市运行。演示地址:http://www.hightopo.com/demo/intelligent-city/entry/dest/index.html预览图:代码实现加载场景首先新建一个场景,将场景添加到页面中。让dm=this.dm=newht.DataModel();让entryG3d=this.entryG3d=newht.graph3d.Graph3dView(dm);entryG3d.addToDOM();//给页面添加场景HT组件一般嵌入在BorderPane、SplitView、TabView等容器中,最外层的HT组件需要用户手动将getView()返回的底层div元素添加到页面的DOM元素中。这里需要注意的是,当父容器的尺寸变化时,如果父容器是HT预定义的容器组件,如BorderPane、SplitView,HT容器会自动递归调用子组件的invalidate函数通知更新。但是如果父容器是原生的html元素,HT组件无法知道它需要更新,所以最外层的HT组件一般需要监听窗口的窗口大小变化事件,调用最外层的invalidate函数要更新的组件。为了方便加载最外层组件填充窗口,HT的所有组件都有addToDOM函数,其实现逻辑如下,其中iv是invalidate的缩写:addToDOM=function(){varself=this,view=self.getView(),//获取组件divstyle=view.style;document.body.appendChild(view);//将组件添加到文档对象style.left='0';style.right='0';style.top='0';style.bottom='0';window.addEventListener('resize',function(){self.iv();},false);//监听窗口变化,刷新组件}接下来逆序转换城市场景json。ht.Default.xhrLoad('scenes/park/citydemo.json',(text)=>{letjson=ht.Default.parse(text);//恢复json字符串letscene=json.scene;//获取json中设置的投影参数entryG3d.setEye(scene.eye);//设置视角entryG3d.setCenter(scene.center);//设置目标中心点远端段位置entryG3d.setNear(scene.near);//设置近端段位置dm.deserialize(text);//场景反序列化this.setSkyBox(entryG3d);//设置天空球this.initentryG3dEvent();//添加场景监听事件this.startAnimate();//启动城市动画this.startCarAnimate(\['car1Line'\],dm.getDataByTag('car1'));//启动消防车1animationthis.startCarAnimate(\['car2Line'\],dm.getDataByTag('car2'));//启动消防车2动画});场景渲染1、环境光贴图:渲染场景中的贴图图像,通过node.s('envmap',0.5)设置节点的渲染等级,主要用于在地板上添加物体反射效果,以及也可以像这个demo一样加上星光点缀。dataModel.setEnvmap('环境光照贴图.png');//地图要求宽度和高度为2^nnode.s('envmap',0.1);对比图:右图环境光图为星光,市中心区域有蓝色星空颜色变化,演示中旋转场景也能看到明显的星光变化。2、辉光:指气体在低压气体中放电的物理现象。它用于突出显示3D场景中的明亮颜色并呈现发光效果。它可以控制发光强度、发光显示范围和发光阈值。g3d.enablePostProcessing('Bloom',true);//启用发光模块=g3d.getPostProcessingModule('Bloom');模块强度=0.18;//强度module.threshold=0.62;//阈值module.radius=0.4;//范围g3d.iv();//刷新拓扑对比图:3.景深:控制场景中心周围的清晰度,虚化周围,美化画面,突出主体,增强透视,控制景深阈值(周围的度数)模糊范围)。g3d.enablePostProcessing('Dof',true);//启用景深module=g3d.getPostProcessingModule('Dof');模组.孔径=0.18;//景深阈值module.image='depthoffieldmap.png';//深度图g3d.iv();//刷新拓扑对比图:可以看到右边图中的卫星区域和最左边的卫星区域变得模糊了。4.天空球体:将场景模型放置在一个大球体中,在球体内部贴上纹理来模拟天空。node=newht.Node()node.s({'shape3d':'sphere',//sphere'shape3d.image':'earth'//纹理路径});node.s3(10000,10000,10000);g3d.dm().add(节点);g3d.setSkyBox(节点);//设置天空球动画实现如下图加载的城市场景:我们可以看到建筑群都有自己的数据展示面板,中心建筑周围有一个孔径列车模型,这是一个模拟的城市中心列车,右侧有一颗城市卫星。现在让我们更改数据面板上的数据,让火车和卫星开始移动。动画是使用调度函数(调度手册)实现的。我们先了解一下调度函数的用法:HT中的调度过程是先通过dataModel添加调度任务,dataModel会在调度任务指定的时间间隔到达,遍历dataModel中的所有primitive并回调调度任务的动作函数。在该函数中,可以修改传入的数据图元的相应属性,实现动画效果。dataModel.addScheduleTask(task)添加定时任务,其中task是一个json对象,可以指定如下属性:interval:间隔时间,单位毫秒,默认10enabled:是否开启开关,默认为trueaction:区间动作函数,该函数必须设置dataModel。removeScheduleTask(task)删除定时任务,其中task是之前添加的定时任务对象。动画实现代码如下:startAnimate(){letdr=Math.PI/180*2,PI2=Math.PI*2;letdm=this.dm;letrotateOval=dm.getDataByTag('rotateOval');//获取城市火车模型letlogo=dm.getDataByTag('logo');//获取城市卫星模型  //设置动画参数 letroatateTask=this.roatateTask={interval:100,action:function(data){if(data===rotateOval||data===logo){data.setRotation((data.getRotation()-dr)%PI2);}}};dm.addScheduleTask(roatateTask);//添加动画到调度任务  //获取建筑数据面板letdglsd=dm.getDataByTag('dglsd');//戴鼓岭隧道letxlsd=dm.getDataByTag('xlsd');//杏林隧道letxmg=dm.getDataByTag('xmg');//厦门港letjcglzx=dm.getDataByTag('jcglzx');//机场管理中心  //模拟建筑数据面板的动态显示letvalueChangeTask=this.valueChangeTask={interval:1000,action:function(data){if(data===dglsd){data.a('carHour',util.randomNumBetween(3000,6000));}if(data===xlsd){data.a('carHour',util.randomNumBetween(3000,6000));}if(data===xmg){data.a('ttl',util.randomNumBetween(3,10));data.a('zy',util.randomNumBetween(0,100));}if(data===jcglzx){data.a('sskll',util.randomNumBetween(500,2000));}}};dm.addScheduleTask(valueChangeTask);//改变数据加入调度任务}实现动画效果如下图:demo也模拟了消防车冲向火灾现场,动画如下:消防车使用ht.Default。startAnim,我们先来了解一下:ht.Default。startAnim({frames:12,//动画帧间隔:10,//动画帧间隔毫秒数easing:function(t){returnt*t;},//动画缓动函数,默认ht.Default.animEasingfinishFunc:function(){console.log('Done!')},//动画结束后调用的函数action:function(v,t){//必须提供动作函数才能实现动画过程中的属性变化node.setPosition(//此示例显示动画节点\`node\`从位置\`p1\`到位置\`p2\`。p1.x+(p2.x-p1.x)*v,p1.y+(p2.y-p1.y)*v);}});以上是Frame-Based动画,用户通过指定动画帧数frames和动画帧间隔参数interval来控制动画效果。ht.Default.startAnim({duration:500,//动画周期的毫秒数,\`ht.Default.animDuration\`action:function(v,t){...}});以上是Time-BasedMode动画,在这种模式下,用户只需要指定duration动画循环的毫秒数,HT就会在指定的时间段内完成动画。由于js语言无法精确控制interval时间间隔,所以使用Frame-Based也无法精确控制动画时间段。即使相同的帧和区间参数在不同的环境下,动画周期也可能存在较大差异。所以HT默认使用Time-Based。基于方法,如果没有设置duration和frames参数,duration参数将被系统自动设置为ht.Default.animDuration值。消防车行驶实现代码如下:startCarAnimate(polylineTagArr,airNode){//传入消防车行驶路线标签(唯一标签)组和消防车模型节点letdm=this.dm;letentryG3d=this.entryG3d;letcurIndex=0;letpolyline=dm.getDataByTag(polylineTagArr\[curIndex\]);//获取火线ht.PolyLine([http://www.hightopo.com/guide/guide/core/shape/ht-shape-guide.html#ref_different](http://www.hightopo.com/guide/guide/core/shape/ht-shape-guide.html#ref_different))letprePos=airNode.p3();//获取节点的初始位置letpreRotate=airNode.r3();//获取节点的初始旋转角度letlineLength=entryG3d.getLineLength(polyline);//获取管道长度letparams={//设置消防车行驶动画参数duration:10000,easing:function(t){returnt*t;},action:function(v,t){letoffset=entryG3d.getLineOffset(polyline,lineLength*v),//获取管道指定比例的偏移信息point=offset.point,px=point.x,py=point.y,pz=point.z,tangent=offset.tangent,tx=tangent.x,ty=tangent.y,tz=tangent.z;airNode.p3(px,py,pz);//将消防车移动到下一个位置airNode.lookAt(\[px+tx,py+ty,pz+tz\],'front');//消防车沿管道方向转弯},finishFunc:function(){if(curIndex