隧道项目是我第一次接触。感觉效果还不错,分享给大家。本次隧道工程主要内容包括:照明、风机、车道指示灯、交通信号灯、信息牌、消防、火警、车辆过孔、风向标、COVI、微波车辆检测、隧道紧急出口控制。本例主要讲一下风向标、排气口和逃生出口的动画设置,点击交通信号灯,弹窗可以选择当前信号灯的信息等等。本例效果:我是用HT做的整个例子,先创建一个3D场景,HT有3D组件,可以直接通过newht.graph3d.Graph3dView3D组件创建实例,然后获取底层div组件通过getView()函数,因为是div,所以位置显示控制就简单多了:dm=newht.DataModel();//数据容器,界面上显示的所有数据都可以存放在数据中containerthroughdataModel.addg3d=newht.graph3d.Graph3dView(dm);//3D组件g3d.addToDOM();//将3D组件的底层div添加到body中。HT组件一般嵌入在BorderPane、SplitView和TabView等容器中,最外层的HT组件需要用户手动将getView()返回的底层div元素添加到页面的DOM元素中。这里需要注意的是,当父容器的尺寸变化时,如果父容器是BorderPane和SplitView等HT预定义的容器组件,HT容器会自动递归调用子组件的invalidate函数通知更新。但是如果父容器是原生的html元素,HT组件无法知道它需要更新,所以最外层的HT组件一般需要监听window的窗口大小变化事件,调用最外层组件的invalidate函数来更新。为了方便加载最外层组件填满窗口,HT的所有组件都有addToDOM函数,实现逻辑如下,其中iv是invalidate的简写:addToDOM=function(){varself=this,view=self.getView(),//获取组件底层divstyle=view.style;document.body.appendChild(视图);//将组件底层div加入bodystyle.left='0';//HT组件默认设置position样式属性为absolute绝对定位方式style.right='0';style.top='0';style.bottom='0';window.addEventListener('resize',function(){self.iv();},false);}最让我开心的是,我的开发和设计部分基本完全分离了,因为HT可以直接通过ht.Default.xhrLoad函数加载json文件的场景,这样我和设计者是双进程的,很开心~加载一个场景分三步,如下:ht.Default.xhrLoad('scenes/tunnel.json',function(text){//加载json场景varjson=ht.Default.parse(text);//转义json文件dm.deserialize(json);//将json内容反序列化到场景中//这里可以任意操作datamodel数据容器中的数据}我在场景中添加了一些功能,包括一些动画操作上文提到,HT封装了dataModel.addScheduleTask(task),通过操作数据容器dataModel来控制加载动画,动画部分在参数task中声明,task是一个json对象,可以指定如下属性:interval:interval的毫秒数,默认值为10enabled:是否开启开关,默认值为trueaction:间隔动作函数,这个函数必须设置我的动画一共三个,两个隧道各有一个风扇,一个风向标和一个卷帘门只需设置这三个原语即可更改。我在json中设置了这三个原语的标签为feng、feng2和door,代码中可以直接调用这三个原语的标签属性:vartask={action:function(data){if(!data.getTag())返回;vartag=data.getTag();//获取图元的标签属性if(tag==='feng'){data.r3(0,(data.r3()[1]+Math.PI/12),0);//r3是3d中的旋转,其中y轴在原图上旋转Math.PI/12角度basis}elseif(tag==='feng2'){data.r3(0,0,data.r3()[2]+Math.PI/12);}elseif(tag==='door'){if(data.getTall()>0){//获取图元的tall属性,高度data.setTall(data.getTall()-20);//设置高度为当前高度减去20}}}}dm.addScheduleTask(task);//在数据容器dataModel中添加调度任务然后创建一个表单form,在表单上添加一些信息,比如流量的切换灯光等。场景中默认显示的右上角的form表单这里不再说明。内容和点击红绿灯时出现的表格类似,所以我们主要讲解点击红绿灯时出现的表格:表格中有很多重复的部分,所以我挑出三个部分来解释:文本部分,“当前状态”显示图标和下方“修改状态”图标点击选择部分:form.addRow([//addRow添加一行。这部分是添加一个标题{元素:'TrafficLightControl',//这一行第一部分的显示文字align:'center',//文字对齐颜色:'rgb(0,210,187)',//文字颜色字体:'bold16pxarial,sans-serif'//文字字体}],[0.1]);//记得设置这一行的宽度form.addRow([//这一行有两部分,一个“设备描述”",一个文本"0",所以需要设置两个宽度,宽度放在一个数组'devicedescription:',//第一部分{//第二部分元素:'0',颜色:'rgb(0,210,187)'}],[80,0.1],34);//addRow函数的第二个参数是宽度设置,将上面内容的宽度依次放入这个数组中第三个参数是高度form.addRow(['Currentstate:',{//也可以设置数组的某部分为空字符串,占用一些宽度,这样比例更容易调整element:''},{id:'105',//id唯一标识属性,可以通过formPane.getItemById(id)添加到对应的item对象中button:{//button,设置该属性后HT会自动构建ht根据属性值.widget.Button对象,保存在元素属性icon上:'symbols/tunnelicon/light.json',//按钮背景上的显示图标:'rgba(0,7,26,0.60)',//按钮背景borderColor:'rgb(0,7,26)',//按钮边框颜色clickable:false//是否可点击}}],[80,0.1,84],30);form.addRow([//如果与上述行的距离差与其他行的距离不同,可以通过添加空行来设置高度'',{element:''}],[200,0.1],10);form.addRow(['modifyStatus:',{element:''},{button:{icon:'symbols/tunnelicon/light.json',//设置按钮的图标背景:'rgba(0,7,26,0.60)',borderColor:'rgb(0,7,26)',groupId:'btn',//通过getGroupId和setGroupId获取和设置组号,属于同一组的切换按钮具有互斥功能.接下来的三个按钮也设置了相同的groupIdonClicked:function(e){//点击后的回调函数btnClick('light');}}}],[80,0.1,84],30);这个表单表单的背景只是一张图片:background:url('assets/control.png')no-repeat;还有一部分上面没有提到,就是点击按钮后调用的btnClick函数:functionbtnClick(imageName){if(flag===1){//根据3d事件进行判断,dm.getDataByTag('light').s({//通过getDataByTag获取节点,设置节点的样式style'back.image':'symbols/iconfortunnel/'+imageName+'.json',//设置的背影theprimitive'front.image':'symbols/iconfortunnel/'+imageName+'.json'//设置你面前的图片元素});}elseif(flag===2){dm.getDataByTag('light1').s({'back.image':'symbols/tunnelicon/'+imageName+'.json','front.image':'隧道的符号/图标/'+imageName+'.json'});}else{}form.getViewById(105).setIcon('symbols/iconfortunnel/'+imageName+'.json');//将id为105的item内容显示的图标设置为该按钮的图标红绿灯点击了窗体}最后还有一个点击事件,一个是点击3D中的红绿灯,出现红绿灯控制的form表单,一个是点击“修改状态”下的图标事件在表单上:g3d.mi(function(e){//addInteractorListener函数监听场景中的事件form.getView().style.display='none';//所有点击原始事件首先隐藏表单if(e.kind==='clickData'){//点击图元if(e.data.getTag()==='light'){//如果图元是前方隧道的光form.getView().style.display='block';//显示表单form.iv();//刷新表单form,否则界面不知道此时需要刷新表单才能显示以上内容,必须手动操作flag=1;}elseif(e.data.getTag()==='light1'){//背面隧道的灯,点击切换隧道灯的显示,其他隧道的灯不能一起变化,所以需要区分form.getView().style.display='block';表格.iv();标志=2;}elseif(e.data.getTag()==='wall'){//隧道墙e.data.s({'shape3d.transparent':true,//打开开关设置透明度'shape3d.opacity':0.2,//设置透明度'3d.selectable':false//点击后不能选中隧道});}}elseif(e.kind==='doubleClickBackground'){//点击空白处设置隧道墙的不透明度dm.getDatas().forEach(function(data){//遍历dataModelif(data.getTag()==='wall'){data.s({'shape3d.transparent':false,//关闭透明开关,这样就不能用于控制透明度'3d.selectable':true//双击空白处使隧道可选});}});}});本文示例地址:http://www.hightopo.com/demo/。..
