基于 HTML5 结合互联网+ 的 3D 隧道

2024-08-30 11:18

本文主要是介绍基于 HTML5 结合互联网+ 的 3D 隧道,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

目前,物资采购和人力成本是隧道业发展的两大瓶颈。比如依靠民间借贷,融资成本很高;采购价格不透明,没有增值税发票;还有项目管控和供应链管理的问题。成本在不断上升,利润在不断下降,隧道产业的“互联网+”迫在眉睫。隧道业的机械化程度高,机械制造和采购成本非常大,此外,隧道业的发展还面临建筑市场的严峻考验。“互联网+”提供大数据、信息流,为传统隧道企业由机械化向数字化挺进提供了机遇,隧道产业的建设工程需要持续的技术支持,也需要经验分享,如果可以借助互联网整理和分享相关经验,将为隧道产业发展带来智慧动力。

通过视频监控图像与语音录像系统,就能随时掌握各工点的施工情况,及时解决施工遇到的问题,从而提高管理效率;在比较特殊的地段,比如大山沟里,点多线长,交通不便,施工组织管理难度大,在传统的施工过程中,基本靠人来回穿梭于各工点之间或电话沟通,检查、监督施工,往往需要很多人参与管理,但仍然管不好,经常出现信息不对称,管理不到位等问题,基于“互联网+”的视频监控图像与语音录像系统应运而生。

 

https://hightopo.com/demo/tunnel2/index.html

代码生成

场景搭建

首先创建 3D 场景,HT(http://hightopo.com) 有 3D 组件,可以直接通过 new ht.graph3d.Graph3dView 3D 组件(https://hightopo.com/guide/guide/core/3d/ht-3d-guide.html)来创建一个实例,然后通过 getView() 函数获取组件的底层 div,既然是 div,那位置显示控制就容易得多了:

dm = new ht.DataModel();// 数据容器,可以将显示在界面上的所有数据通过 dataModel.add 存储在数据容器中
g3d = new ht.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(){   var self = this,view = self.getView(),// 获取组件的底层 divstyle = view.style;document.body.appendChild(view);// 将组件的底层 div 添加进 body 中           style.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/隧道.json', function(text){// 加载 json 场景var json = ht.Default.parse(text);// 转义 json 文件dm.deserialize(json);// 将 json 内容反序列化到场景中// 可以在这个里面任意操作 datamodel 数据容器中的数据了
}

动画

我在场景中添加了一些功能,包括前面提到过的一些动画操作,HT 封装好的 dataModel.addScheduleTask(task) 通过操作数据容器 dataModel 来控制加载动画(https://hightopo.com/guide/guide/core/schedule/ht-schedule-guide.html),动画部分在参数 task 中声明,task 为 json 对象,可指定如下属性:

  • interval:间隔毫秒数,默认值为 10
  • enabled:是否启用开关,默认为 true
  • action:间隔动作函数,该函数必须设置

我的动画一共三个,两个隧道中各有一个风扇、一个风向仪以及一个卷闸门。设置这三个图元变化即可,我在 json 中分别将这三个图元的 tag 设置为 feng、feng2 以及 door,在代码中我就可以直接调用这三个图元的 tag 属性:

var task = {action: function(data){if(!data.getTag()) return;var tag = data.getTag();// 获取图元的 tag 属性if(tag === 'feng'){data.r3(0, (data.r3()[1]+Math.PI/12), 0);// r3 为 3d 中的旋转,这里 y 轴在原来的基础上再旋转 Math.PI/12 角度}else if(tag === 'feng2'){data.r3(0, 0, data.r3()[2]+Math.PI/12);}else if(tag === 'door'){if(data.getTall() > 0){// 获取图元的 tall 属性,高度data.setTall(data.getTall()-20);// 设置高度为当前高度减去20}}}
}
dm.addScheduleTask(task);// 在数据容器 dataModel 中添加调度任务

接着是创建 form 表单,在表单上添加一些信息,比如交通灯的切换等等,场景默认显示的右上角的 form 表单我们这里不做解释,内容跟点击交通灯出现的 form 表单差不多,所以我们主要说明一下点击交通灯时出现的表单:

表单中重复的部分比较多,我挑出三个部分来解释一下:文本部分、“当前状态”显示的图标以及下面“修改状态”中的图标点击选择部分:

form.addRow([// addRow 添加一行 我这个部分是添加一个标题{element: '交通灯控制',// 这一行第一部分的显示文本align: 'center',// 文本对齐方式color: 'rgb(0,210,187)',// 文本颜色font: 'bold 16px arial, sans-serif'// 文本字体}
], [0.1]);// 记得要设置这行的宽度
form.addRow([ // 这行中有两个部分,一个“设备描述”,一个 文本“0”,所以要设置两个宽度,宽度要放在一个数组中      '设备描述:',// 第一部分{// 第二部分element: '0',color: 'rgb(0,210,187)'}
],[80, 0.1], 34);// addRow 函数第二个参数为宽度设置,将上面内容的宽度依次放进这个数组中。第三个参数为高度
form.addRow([     '当前状态:',{// 也可以将数组中的某个部分设置为空字符串,占据一些宽度,这样比例比较好调element: ''},{id: '105',// id唯一标示属性,可通过formPane.getItemById(id)获取添加到对应的item对象button: {/ /按钮,设置了该属性后HT将根据属性值自动构建ht.widget.Button对象,并保存在element属性上icon: 'symbols/隧道用图标/light.json',// 按钮上的显示图标background: '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([                    '修改状态:',{element: ''},{button: {icon: 'symbols/隧道用图标/light.json',// 设置按钮的图标background: 'rgba(0,7,26,0.60)',borderColor: 'rgb(0, 7, 26)',groupId: 'btn',// 通过getGroupId和setGroupId获取和设置组编号,属于同组的togglable按钮具有互斥功能。后面的三个按钮也是设置了同一个 groupIdonClicked: function(e){// 点击后的回调函数btnClick('light'); }}}
],[80, 0.1, 84], 30);

这个 form 表单的背景只是设置了一张图片而已:

background: url('assets/控制.png') no-repeat;

上面还有一个部分没有提及,就是点击按钮后调用的 btnClick 函数:

function btnClick(imageName){if(flag === 1){// 做的判断是根据3d的事件来处理的,等下会提dm.getDataByTag('light').s({// 通过getDataByTag获取节点,设置节点的style样式'back.image': 'symbols/隧道用图标/'+imageName+'.json',// 设置图元的背面图片'front.image': 'symbols/隧道用图标/'+imageName+'.json'// 设置图元你的前面图片});}else if(flag === 2){dm.getDataByTag('light1').s({'back.image': 'symbols/隧道用图标/'+imageName+'.json','front.image': 'symbols/隧道用图标/'+imageName+'.json'});}else{}form.getViewById(105).setIcon('symbols/隧道用图标/'+imageName+'.json');// 设置id为105的item内容显示的图标为form表单上点击的交通灯的按钮的图标
}

最后就是点击事件了,点击交通灯会直接切换交通灯的颜色(实际上是切换模型的贴图):

g3d.mi(function(e){// addInteractorListener 函数 监听场景中的事件if(e.kind === 'clickData') {if (e.data.getTag() === 'jam') { createDialog(e.data); }else if (e.data.getTag() === 'light') {// 如果图元是背面的隧道的灯var frontImage = e.data.s('front.image');var imageName = frontImage.slice(frontImage.lastIndexOf('/')+1, frontImage.lastIndexOf('.'));btnClick('light', imageName);}else if (e.data.getTag() === 'light1'){// 正面的隧道的灯var frontImage = e.data.s('front.image');var imageName = frontImage.slice(frontImage.lastIndexOf('/')+1, frontImage.lastIndexOf('.'));btnClick('light1', imageName);}}
});

互联网+的概念在新兴产业上能够很好地运营,同时在传统行业中利用得当同样能够产生非常大的效益,比如智慧城市建设,智慧能源管理,智慧工厂,甚至是地铁监管等等都可以结合互联网+的模式来运作,在一定程度上节省了非常多的人力和时间成本。

https://hightopo.com/demo/bigscreen-newenergy/

https://hightopo.com/demo/intelligent-plant/

https://hightopo.com/demo/metro/demo2.html

这篇关于基于 HTML5 结合互联网+ 的 3D 隧道的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1120663

相关文章

Python结合requests和Cheerio处理网页内容的操作步骤

《Python结合requests和Cheerio处理网页内容的操作步骤》Python因其简洁明了的语法和强大的库支持,成为了编写爬虫程序的首选语言之一,requests库是Python中用于发送HT... 目录一、前言二、环境搭建三、requests库的基本使用四、Cheerio库的基本使用五、结合req

vue解决子组件样式覆盖问题scoped deep

《vue解决子组件样式覆盖问题scopeddeep》文章主要介绍了在Vue项目中处理全局样式和局部样式的方法,包括使用scoped属性和深度选择器(/deep/)来覆盖子组件的样式,作者建议所有组件... 目录前言scoped分析deep分析使用总结所有组件必须加scoped父组件覆盖子组件使用deep前言

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

React实现原生APP切换效果

《React实现原生APP切换效果》最近需要使用Hybrid的方式开发一个APP,交互和原生APP相似并且需要IM通信,本文给大家介绍了使用React实现原生APP切换效果,文中通过代码示例讲解的非常... 目录背景需求概览技术栈实现步骤根据 react-router-dom 文档配置好路由添加过渡动画使用

如何用Java结合经纬度位置计算目标点的日出日落时间详解

《如何用Java结合经纬度位置计算目标点的日出日落时间详解》这篇文章主详细讲解了如何基于目标点的经纬度计算日出日落时间,提供了在线API和Java库两种计算方法,并通过实际案例展示了其应用,需要的朋友... 目录前言一、应用示例1、天安门升旗时间2、湖南省日出日落信息二、Java日出日落计算1、在线API2

使用Vue.js报错:ReferenceError: “Vue is not defined“ 的原因与解决方案

《使用Vue.js报错:ReferenceError:“Vueisnotdefined“的原因与解决方案》在前端开发中,ReferenceError:Vueisnotdefined是一个常见... 目录一、错误描述二、错误成因分析三、解决方案1. 检查 vue.js 的引入方式2. 验证 npm 安装3.

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

python解析HTML并提取span标签中的文本

《python解析HTML并提取span标签中的文本》在网页开发和数据抓取过程中,我们经常需要从HTML页面中提取信息,尤其是span元素中的文本,span标签是一个行内元素,通常用于包装一小段文本或... 目录一、安装相关依赖二、html 页面结构三、使用 BeautifulSoup javascript

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template