前言
工业物联网在中国的发展如火如荼,网络基础设施建设,以及工业升级的迫切需要都为工业物联网发展提供了很大的机遇。中国工业物联网企业目前呈现两种发展形式并存状况:一方面是大型通讯、IT企业的布局;一方面是传统工业软件和工业网络企业自发地延伸,由产品提供商发展为方案供应商。什么叫做裙房?裙房是指附属于主高楼并与之连成一体的低层建筑。本文的 Demo 是针对于裙房做的,但是在工业监控系统中有很多雷同的部分,比如动画、点击切换、点击隐藏、故障展示、开关、数据展示等等,都是比较通用的一些功能。所以针对这个 Demo 将这些内容做一个记录,在这个 Demo 中我也遇到了一些问题,如何解决的都会拿出来跟大家分享。
http://www.hightopo.com/demo/annexMonitor/
代码实现
整个 Demo 我们要实现的部分有:
- 3D 场景的搭建
- 场景中叶轮的转动
- 容器水位的上升下降
- 叶轮转动故障展示
- 开启/关闭动画
- 灯光的开启/关闭
- 点击切换模型
- 点击隐藏/显示属性窗口
- 文本内容/颜色变换
上面的功能看起来蛮多的,实际上实现起来还是比较容易的,总共就用了 200+ 行的代码。
3D 场景搭建
三维场景地基的搭建就 2 行代码:
var g3d = new ht.graph3d.Graph3dView();// Hightopo 的 3D 组件(三维场景地基) g3d.addToDOM();// 将 3D 组将添加到 body 体中
addToDOM = function(){ var self = this, view = self.getView(),//获取组件的底层 div style = 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);//窗口大小改变事件,调用刷新函数 }
接下来我们要向场景中添加各种模型,用代码生成模型是非常无敌痛苦的,我们将整个场景的模型都放到一个 JSON 文件中,并通过 ht.Default.xhrLoad 方法将这个 JSON 转换为 3D 场景显示在界面上:
var dm = g3d.dm();// 获取 HT 3D 组件的数据容器 ht.Default.xhrLoad('scenes/system.json', function(text) { dm.deserialize(text);// 将函数的 text(json)参数传给 deserialize 反序列化方法,可将 json 内容中的元素添加到 dataModel 数据容器中进行显示 }
ht.Default.xhrLoad 方法是一个异步加载 json 文件的方法,第一个参数为传入的 json 文件,路径是相对于 html 文件的,第二个参数是回调函数,在传入的 json 文件解析完毕之后做的操作。此方法为异步加载,因此需要对 dm 数据容器中的数据进行获取或操作的话,需要将获取/操作的代码写在 dm.deserialize(text) 方法之后,因为此时 dm 数据容器中才有节点。
上面将 JSON 文件发序列化到 dm 数据容器中后界面显示如下:
上图中整个场景的背景是我后期用代码添加的,通过前面的 addToDOM 函数可以知道我们可以通过 getView 方法获取 HT 3D 组件的底层 div,因此要在此 div 上添加一张背景图也就不难了。剩下的 3D 模型部分都是由 JSON 反序列化出来的。
场景中叶轮的转动
当然转动不可能是整个模型在转动,而是中间的“滚轮”在转动,这要求设计师在创建模型的时候就将这个部分分离出来,然后我给此部分设置 tag 唯一标识为“yelun”,通过 dm.getDataByTag('yelun') 即可获取到这个节点,然后给这个节点设置旋转动画。
HT 中调度进行的流程是,先通过 DataModel(https://hightopo.com/guide/guide/core/datamodel/ht-datamodel-guide.html) 添加调度任务,DataModel 会在调度任务指定的时间间隔到达时, 遍历 DataModel 所有图元回调调度任务的 action 函数,可在该函数中对传入的 Data 图元做相应的属性修改以达到动画效果。
根据上面对调度任务的说明,我们了解到向 dm 数据容器中添加调度任务会遍历整个数据容器,数据容器中内容不多的时候可能感觉不到,但当数据容器中内容多且模型重的情况下,对 dm 数据容器进行过滤就非常有必要了,而且如果添加多个调度任务都遍历了整个数据容器,那么对电脑的性能要求可想而知。我一开始使用的时候就是遗漏了对 dm 数据容器的过滤,因为场景不大,所以一开始没有感觉,后来加了灯光后很重,就立马出现问题了,但是一直找不到原因,后来在高人指点下才发下遗漏了对 data 的过滤判断。
因此,调度任务传入的参数对象中 action 方法传入了一个 data 值,用于设置当前动画的对象,不是此对象的直接可以 return 掉,不做任何操作:
var task = []; var yelun = dm.getDataByTag('yelun');// 获取 tag 为 yelun 的节点 // 创建一个动画调度任务 task.yelunTask = { interval: 100,// 动画持续时间 action: function(data) {// 动画内容 if (data !== yelun) return; // 设置 yelun 节点的 x 轴旋转为当前 x 轴旋转值再加上 Math.PI/12 yelun.setRotationX(yelun.getRotationX() + Math.PI/12); } } dm.addScheduleTask(task.yelunTask);// 将调度任务添加到数据容器中
容器水位的上升下降
这里将容器水位的上升下降放到一个动画调度任务里了,也就是说通过 dm 数据容器操作这个调度任务就能够同时操作这两个部分的动画,将上一小节中的 yelunTask 调度任务的 action 更改一下,因为上面的代码只对 yelun 节点进行了操作,我们需要对装水的容器也进行操作。首先获取装水的容器,这里将这个节点的唯一标识 tag 设置为“cylinder”:
var cylinder = dm.getDataByTag('cylinder');
然后更改调度中的 action 部分代码:
action: function(data) { if (!(data === yelun || data === cylinder)) return; // 叶轮转动 yelun.setRotationX(yelun.getRotationX() + Math.PI/12); // 容器水位变化 if (cylinder.getTall() === 100) { cylinder.setTall(0);// 容器水位高度到达 100 的值时,重置为 0 } else cylinder.setTall(cylinder.getTall() + 1); }
叶轮转动故障展示
因为没有数据的传输,所以这边故障信息我只能自己造假数据了,我创建了一个 10 以内的整数随机数,判断这个值是否为 1,如果为 1 就将运作正常的图标变换成告警图标,同时我还通过这个值来设置 dm 数据容器添加/移除调度任务来控制当前叶轮转动/停止、容器水位变化与否:
var alarm = dm.getDataByTag('alarm');// 获取告警图标节点 setInterval(function() { var random = Math.floor(Math.random()*5); if (random === 1) { alarm.s('shape3d.image', 'symbols/电信/故障 2.json');// 设置告警图标节点为“故障”图标 dm.removeScheduleTask(task.yelunTask);// 将叶轮的动画加上 } else { alarm.s('shape3d.image', 'symbols/电信/正常 2.json');// 设置告警图标节点为“正常”图标 dm.addScheduleTask(task.yelunTask);// 移除叶轮的动画 } }, 1000);
开启/关闭动画
上一小节我们已经提到了开启/关闭动画的方式,这边我们运用 form 表单,手动操作动画的开启和关闭(注:这里只说明第一行的“水流开关”)。
首先,我们需要创建一个 formPane 表单组件(https://hightopo.com/guide/guide/plugin/form/ht-form-guide.html),在这个表单组件中添加行数据,这边操作动画的开启和关闭我是用的 checkbox,值变化只有 true 和 false,这个情况用这个是比较优的选择。然后通过监听这个 checkbox 的值的变化事件,设置动画的开启(添加)或者关闭(移除)。
function createForm(task) { var form = new ht.widget.FormPane();// 创建 form 表单组件对象 form.setWidth(160);// 设置表单组件的宽度 form.setHeight(90);// 设置表单组件的高度 // 设置表单组件底层 div 的样式属性 form.getView().style.right = '10px'; form.getView().style.top = '10px'; form.getView().style.background = 'rgba(255, 255, 255, 0.2)'; form.getView().style.borderRadius = '5px'; document.body.appendChild(form.getView());// 将 form 表单底层 div 添加到 body 体中 // 水阀开启和关闭 form.addRow([// 给 form 表单添加一行数据 { checkBox: {// 复选框类,HT 将此封装到 form 中 实际上创建了一个 ht.widget.CheckBox 组件 label: '水流开关',// 设置 checkbox 的文本内容 labelColor: '#fff',// 设置 checkbox 文本颜色 selected: true,// 设置此 checkbox 是否选中 onValueChanged: function() {// 监听值变化事件 if (this.isSelected()) dm.addScheduleTask(task.arrowTask);// 如果这个 checkBox 选中,则添加动画(开启水阀) else dm.removeScheduleTask(task.arrowTask);// 如果这个 checkBox 未被选中,则移除动画(关闭水阀) } } } ], [0.1]);// 设置这个行数据中列的宽度 return form; }
addRow 方法上面代码中一言两语解释不清楚,参考如下说明:
addRow(items, widths, height, params) 添加一行组件
- items为元素数组,元素可为字符串、json 格式描述的组件参数信息、html 元素或者为 null 的空
- widths 为每个元素宽度信息数组,宽度值大于 1 代表固定绝对值,小于等于 1 代表相对值,也可为 80+0.3 的组合
- height 为行高信息,值大于 1 代表固定绝对值,小于等于 1 代表相对值,也可为 80+0.3 的组合,为空时采用默认行高
- params 为 json 格式的额外参数,例如插入行索引以及行边框或背景颜色等,如{index: 2, background: 'yellow', borderColor: 'red'}
上面代码中提到的 arrowTask 是对场景中的“箭头”流动添加的动画调度任务,通过控制 form 表单中 checkbox 复选框是否选中可直接操作 dm 是否添加/移除动画调度任务。
灯光的开启/关闭
控制灯光的开启和关闭,这里也是通过 form 表单上的 checkbox 复选框来进行操作的。一般建议不要使用灯光,渲染太烧性能了,这里只是为了效果而添加做一个说明。
首先我们需要创建一个“灯”节点,然后通过设置样式属性 setStyle 来设置灯的类型、颜色、灯照范围等等属性:
// 添加灯光 var light = new ht.Light();// 创建一个灯节点(继承于 ht.Node) (https://hightopo.com/guide/guide/core/lighting/ht-lighting-guide.html) light.p3([15, 120, 50]);// 设置此节点的位置 light.setTag('light');// 设置此节点的唯一标识 dm.add(light);// 将此节点添加到 dm 数据容器中进行显示 light.s({// 设置此节点的样式属性 setStyle 简写为 s 'light.type': 'point',// 设置灯类型 'light.color': 'rgb(252,252,149)',// 设置灯颜色 'light.range': 1400,// 设置灯照范围 '3d.visible': false// 设置此节点在 3d 上不可见 });
然后在 form 表单上添加一行用来控制灯的开关、灯的颜色灯功能:
// 9、灯光开启和关闭 以及颜色切换 form.addRow([// form 中添加一行 { id: 'lightDisabled',// 设置此项的 id 值,可通过 form.getItemById 获取此项 checkBox: {// 复选框组件 label: '开关灯',// 设置复选框文本内容 labelColor: '#fff',// 设置复选框文本颜色 selected: true,// 设置复选框是否选中 onValueChanged: function() {// 监听值变化事件 dm.getDataByTag('light').s('light.disabled', !this.getValue());// 获取灯节点并设置是否关闭灯光效果,light.disabled 属性默认为false,可设置为true关闭灯效果 } } }, { colorPicker: {// 颜色选择器组件 value: 'rgb(252,252,149)',// 设置当前值 instant: true,// 设置是否处于即时状态,将会实时改变模型值 onValueChanged: function() {// 监听值变化事件 dm.getDataByTag('light').s('light.color', this.getValue())// 设置灯的颜色为当前选中的颜色 } } } ], [0.1, 0.1]);
点击切换模型
HT 将事件监听封装到 mi 事件(https://hightopo.com/guide/guide/core/3d/ht-3d-guide.html#ref_interactionlistener)中,mi 方法中有多种事件,这里我们需要的是单击节点的事件监听 clickData 事件,通过判断事件类型 e.kind 是否为 clickData,之后对节点的设置模型即可:
var waterPump6 = dm.getDataByTag('水泵06');// 获取 tag 为“水泵06”的节点 waterPump6.s({// 设置该节点的样式属性 'note': '点我切换模型',// 设置标注文字内容 'note.transparent': true,// 设置标注在 3D 下是否透明 'note.t3': [0, 0, -50],// 设置标注在 3D 下的偏移 'note.reverse.flip': true//设置标注背面是否显示正面的内容 }); g3d.mi(function(e) {// 监听 3D 组件上的事件 if(e.kind === 'clickData') {// 点击节点事件 // 模型点击切换 if (e.data === waterPump6 && e.data.s('shape3d') === 'models/裙房系统/水泵.json') e.data.s('shape3d', 'models/fengji.json');// 设置点击节点的 shape3d 样式属性 else if (e.data === waterPump6 && e.data.s('shape3d') === 'models/fengji.json') e.data.s('shape3d', 'models/裙房系统/水泵.json');// 设置点击节点的 shape3d 样式属性 } });
HT 设置模型是通过设置节点的样式属性 node.setStyle(简写为 node.s)为 shape3d 来实现的。
点击隐藏/显示属性窗口
上面说到了事件的监听,既然同为点击事件,我们就在一个监听事件里面进行具体的操作即可,在上面的 if (e.kind === 'clickData') 判断中添加显示/隐藏属性窗口的逻辑:
var waterPump5 = dm.getDataByTag('水泵05'); waterPump6.s({ 'note': '点我切换模型', 'note.transparent': true, 'note.t3': [0, 0, -50], 'note.reverse.flip': true }); g3d.mi(function(e) { if(e.kind === 'clickData') { // 模型点击切换 if (e.data === waterPump6 && e.data.s('shape3d') === 'models/裙房系统/水泵.json') e.data.s('shape3d', 'models/fengji.json'); else if (e.data === waterPump6 && e.data.s('shape3d') === 'models/fengji.json') e.data.s('shape3d', 'models/裙房系统/水泵.json'); // 模型点击 隐藏/显示属性窗口 if (e.data === waterPump5) {// 判断点击的图元是否为 waterPump5 if(giveWater.s('3d.visible')) {// 判断当前属性窗口是否为显示状态 giveWater.s('3d.visible', false);// 设置属性窗口不可见 e.data.s('note', '点我显示属性窗口');// 更改标注中的显示内容 } else { giveWater.s('3d.visible', true);// 设置属性窗口可见 e.data.s('note', '点我隐藏属性窗口')// 更改标注中的显示内容 } } } });
文本内容/颜色变换
通过 tag 获取场景中对应的属性窗口的节点,此节点为一个面板,相当于六面体有六面,这个节点类型就只有一面,并通过设置属性 shape3d.image 设置此节点上的图片为 tooltips.json 矢量图标(https://hightopo.com/guide/guide/core/vector/ht-vector-guide.html)。矢量在 Hightopo(HT)中是矢量图形的简称,常见的 png 和 jpg 这类的栅格位图, 通过存储每个像素的颜色信息来描述图形,这种方式的图片在拉伸放大或缩小时会出现图形模糊,线条变粗出现锯齿等问题。 而矢量图片通过点、线和多边形来描述图形,因此在无限放大和缩小图片的情况下依然能保持一致的精确度。而且 HT 的矢量图形还有一个非常重要的特点,就是能够对矢量图形上的任何一个部分都进行数据绑定,也就是说上图中的五张图,我们可以只绘制一张图,通过数据绑定来改变这张图上的文本以及数值内容。
矢量图标中的数据绑定可以用在工业中的生产看板、大屏中的数据显示等等,都能够以一种高效的方式进行产品的整合。
矢量图形的数据绑定能够再写一篇文章进行阐述了,这里就不多提,大家自行去官网上查看“矢量手册”以及“数据绑定手册”,说明的比较详细。
获取到对应的节点之后,通过 node.a 方法可以获取和设置数据绑定(https://hightopo.com/guide/guide/core/databinding/ht-databinding-guide.html#ref_vector)的属性,这里我们绑定的是文本内容“label”和数值“value”以及数值颜色“valueColor”:
var billboardArray = []; // 通过 tag 获取节点 var temperature1 = dm.getDataByTag('回水温度1');// 获取 tag 为"回水温度1"的节点 billboardArray.push(temperature1); var temperature2 = dm.getDataByTag('回水温度2'); billboardArray.push(temperature2); var returnPress = dm.getDataByTag('回水压力'); billboardArray.push(returnPress); var givePress = dm.getDataByTag('供水压力'); billboardArray.push(givePress); var giveTemp = dm.getDataByTag('供水温度'); billboardArray.push(giveTemp); var giveWater = dm.getDataByTag('供水流量'); billboardArray.push(giveWater); // 文字标签内容变换 billboardArray.forEach(function(billboard) { billboard.a('label', billboard.getTag());// 设置数据绑定属性为 label 的属性值为当前节点的 tag 内容 }); // 文字标签数字变换+颜色变换 更改图标中绑定的 value 属性值 setInterval(function() { billboardArray.forEach(function(billboard) { var random = Math.random()*100; billboard.a('value', random.toFixed(2)); // 设置图标中“数值内容颜色” if (random > 70 && random <= 80) billboard.a('valueColor', '#00FFFF'); else if (random > 80 && random <= 90) billboard.a('valueColor', '#FFA000'); else if (random > 90) billboard.a('valueColor', '#FF0000'); else billboard.a('valueColor', ''); }); }, 1000);
相关推荐
HTML5 WebGL 3D 仓储管理系统是一种利用现代网络技术实现的高效、直观的库存管理解决方案。这个系统通过在网页上构建三维模型,为用户提供了更真实、更直观的仓库环境展示,使得库存物品的管理变得更加可视化和易于...
仓储系统!仓库管理可以说即不省力也不省事,而且使用范围还很广,数学中经常使用仓储系统来计算市场需求,物流中的动力学建模等等,所以仓储系统必不可少,在这个时间就是金钱的时代,能省时就能带来非常大的效益,...
基于HTML5 WebGL 3D樱花飘落动画 1.网页作品简介 :HTML期末大学生网页设计作业 A+水平 ,喜欢的可以下载,文章页支持手机PC响应式布局。 2.网页作品编辑:作品下载后可使用任意HTML编辑软件(如:DW、HBuilder、...
基于HTML5 WebGl的VR DEMO展示了如何利用WebGL技术创建沉浸式的虚拟现实环境。这个DEMO项目(WebGL-VR-master)可能包含了实现VR体验所需的各种文件,如HTML文件、JavaScript代码、CSS样式表以及可能的纹理图片和...
用 WebGL 渲染的 3D 机房现在也不是什么新鲜事儿了,这篇文章的主要目的是说明一下,3D 机房中的 eye 和 center 的问题,刚好在项目中用上了,好生思考了一番,最终觉得这个例子最符合我的要求,就拿来作为记录。...
总之,"HTML5 WebGL酷炫3D旋转星云动画特效"是结合HTML5的WebGL技术和JavaScript的创新应用,通过精心设计的代码和视觉效果,为用户呈现了一种极具沉浸感的3D体验。对于想要学习WebGL或者提升网页互动性的开发者来说...
总的来说,"基于WebGL实现3D图片特效"是一个结合HTML5库和WebGL技术的创新应用,通过编程技巧将2D图像转化为互动式的3D视图,为用户带来生动的视觉体验。开发者通过理解并运用JavaScript、WebGL和相关的HTML5库,...
HTML5是下一代网页标记语言,它的出现极大地扩展了网页的交互性和功能,其中WebGL(Web Graphics Library)是一项关键的技术,它使得浏览器可以直接在用户的设备上进行硬件加速的3D图形渲染,无需任何插件。WebGL...
在本示例中,"SuperMap-webgl3D vue示例demo"是一个基于SuperMap、WebGL3D技术以及Vue.js框架构建的三维地球展示应用。这个项目旨在为开发者提供一个直观的学习平台,以理解如何将这些技术整合到一起,创建交互式的...
仓储管理系统(WMS)是一个实时的计算机软件系统,它能够按照运作的业务规则和运算法则,对信息、资源、行为、存货和分销运作进行更完美地管理,使其最大化满足有效产出和精确性的要求。从财务软件、进销存软件CIMS...
HTML5、CSS和WebGL是现代网页开发中的关键技术,它们共同为创建互动性强、视觉效果丰富的3D网页游戏提供了强大的支持。在这个经典教程中,我们将深入探讨这些技术如何结合,以构建引人入胜的网页游戏。 HTML5是超...
基于WebGL的3D试衣系统设计与实现的知识点主要包括以下方面: 1. WebGL技术基础:WebGL是一种3D图形API,能够在不需要插件的情况下在浏览器中运行。它使用OpenGL ES的JavaScript绑定,可以调用显卡硬件加速功能来...
1. **WebGL基础**:WebGL是基于OpenGL ES 2.0的JavaScript API,用于在HTML5的`<canvas>`元素中绘制交互式3D图形。它使用着色器语言(GLSL)编写顶点和片段着色器,这些着色器负责计算每个像素的颜色和位置。 2. **...
"Threejs 开发指南:基于 WebGL 和 HTML5 在网页上渲染 3D 图形和动画" 本文将对 Threejs 开发指南进行详细的介绍,包括 Threejs 的重要性、与其他 3D 渲染技术的比较、为什么要使用 Threejs 等。 首先,Threejs ...
档案管理系统是通过建立统一的标准以规范整个文件管理,包括规范各业务系统的文件管理的完整的档案资源信息共享服务平台,主要实现档案流水化采集功能。为企事业单位的档案现代化管理,提供完整的解决方案,档案管理...
这个项目不仅展示了HTML5和WebGL的结合使用,还涉及到了粒子系统、3D图形、动画以及可能的物理模拟概念。这样的特效可以用于网页背景、节日主题或者任何需要动态视觉效果的场景,为用户带来更生动的浏览体验。
在“个人在北大青鸟做的WebGL3D网页”项目中,我们可以看到一个爱好者如何利用WebGL技术将对3D的热情转化为实际的网页应用。 首先,WebGL允许开发者在浏览器中直接编写图形着色器,这是通过GLSL(OpenGL Shading ...
这个"HTML5+WebGL实现可拖拽的3D透明杯子效果源码.zip"文件,显然包含了一个使用这两种技术制作的互动3D模型示例,特别是一个可以被用户拖动的透明3D杯子。 首先,我们需要了解HTML5中的拖放(Drag and Drop)API。...