基于 HTML5 的工业组态高炉炼铁 3D 大屏可视化
前言
在大数据盛行的现在,大屏数据可视化也已经成为了一个热门的话题。大屏可视化可以运用在众多领域中,比如工业互联网、医疗、交通、工业控制等等。将各项重要指标数据以图表、各种图形等形式表现在一个页面上,各种数据一目了然。随着浏览器不断发展完善,使用 Web 做大屏展示也已经不是新鲜的事了。市面上已有不少的大屏解决方案,大部分是以放各种图表的形式呈现,基本是是 2D 的呈现。有些是根据投放屏幕的比例设计出来的,并不能自适应于其它的屏幕比例。最近学习了 Hightopo 的 HT for Web 产品,特有的矢量,在各种比例下不失真,加上布局机制,解决了不同屏幕比例下的展示问题,加上 3D 的呈现部分,可以做出别具一格的大屏系统。在这里与大家分享学习,先来张整体效果图:

链接:http://www.hightopo.com/demo/large-screen-puddling/
本文主要介绍内容如下,文章中以 HT 作为 HT for Web 的简称:
- 页面搭建
- 数据对接
- 动画效果实现
- 其他细节优化
一、页面搭建
在这个系统中,我们需要创建 ht.graph.GraphView 和 ht.graph3d.Graph3dView 来呈现 2D 和 3D 的内容。设计师给到的 display.json 是 2D 图纸的内容,主要是使用矢量绘制呈现,有一些图表是用了 Echarts,HT 也有机制可以让我们使用它们。scene.json 是 3D 场景的内容,大部分模型都是通过 3dMax 建模生成的,该建模工具可以导出 obj 与 mtl 文件,在 HT 中可以通过解析 obj 与 mtl 文件来生成 3d 场景中的所有复杂模型,简单的模型也可以通过 HT 来建模。关键代码如下:
var g2d = new ht.graph.GraphView();
var g3d = new ht.graph3d.Graph3dView(); // 将 3D 组件加入到 body 下
g3d.addToDOM();
// 将 2D 组件加入到 3D 组件的根 div 下,父子 DOM 事件会冒泡,这样不会影响 3D 场景的交互
g2d.addToDOM(g3d.getView()); g2d.deserialize('display.json', function(json, dm, g2d, datas){
// TODO 2D 反序列化完成回调,后面会讲到
});
g3d.deserialize('scene.json', function(json, dm, g3d, datas) {
// TODO 3D 反序列化完成回调,后面会讲到
});
二、数据对接
页面加载出来后,就可以与后台通讯,请求相关数据对接到对应的元素上了。HT 一大强项是作为 Web 组态,所以有很友好的数据绑定方式,我们可以轻松将数据展示到各个节点上。我们这个案例采用随机数模拟的方式模拟展示数据,在 json 中对相应的节点设置唯一标识 tag,在反序列化完成后,通过 g2d.dm().getDataByTag(tag) 来获得相应节点,再根据这个节点的数据绑定来将数据展示到改节点上。

以下是上面这个表格数据对接的代码,它的 tag 是 alarmTable
// 模拟数据
var mockData = [
{ "time": "2019-02-17 21:54:31", "warningDesc": "11_15冷却壁发生渣皮减薄" },
{ "time": "2019-02-17 21:57:49", "warningDesc": "炉缸热损失正常" },
{ "time": "2019-02-17 22:00:34", "warningDesc": "8_12冷却壁发生渣皮减薄" },
{ "time": "2019-02-17 22:03:44", "warningDesc": "8_12冷却壁发生渣皮减薄" },
{ "time": "2019-02-17 22:07:09", "warningDesc": "11_15炉缸热损失正常" },
{ "time": "2019-02-17 22:11:35", "warningDesc": "8_12冷却壁发生渣皮减薄" },
{ "time": "2019-02-17 22:16:24", "warningDesc": "11_15局部小气流" }
]; var dm = g2d.dm();
var table = dm.getDataByTag('alarmTable');
table.a('ht.dataSource', mockData);
以上表格是一个用 ht 定义的矢量节点,矢量由一个个组件组成,组件不仅可以预定义的矩形,文本等内容,也可以引用其它定义好的矢量,甚至可以自定义绘制逻辑,这个表格就由此而来。矢量不仅可以用在 2D 图纸里,还可以用在 3D 贴图中,在我们 3D 场景中,以下截图的几个面板也是使用矢量实现,

HT 中数据都由 DataModel 驱动,所以 3D 对接数据也是一样的,这里就不再赘述。
三、动画效果实现
- 铁水罐车动画
这个案例中最明显的动画应该就是铁水罐车的动画了,我们先来聊聊它的实现。基本流程是这样的
如上,我们依然是在反序列化完成后,通过 car = g3d.dm().getDataByTag('car'); 得到铁水罐车的节点对象。
通过 car.s('3d.visible', true | false); 就可以控制它的显隐。
通过不断修改节点的 3D 坐标就可以实现位移效果 car.setPosition3d(x, y, z);
至于铁水罐车上的面板,也是个矢量,将它吸附于铁水罐车节点,它就会跟随车移动,不需要单独控制它的坐标来实现动画。
- 管道中气体流动动画

这部分动画效果,只要不断修改贴图的 uv 值就可以实现,以下是示例代码,node 还是由 getDataByTag 得来
var offset1 = 0.03;
setInterval(function () {
node.s({
'top.uv.offset': [-offset1, 0],
'front.uv.offset': [-offset1, 0],
});
offset1 += 0.1;
}, 100);
上料履带的动画也是相同的实现方式

四、其他细节优化
在点击 2D 有点到图元像素时,我们希望不触发 3D 的交互,比如拖动表格滚动时,3D 场景也会跟着旋转。可以通过如下代码控制:
var handler = function(e) {
if (gv.getDataAt(e)) { // 如果点击到的位置有节点信息
e.preventDefault();
e.stopPropagation();
}
}
gv.getView().addEventListener('mousedown', handler);
gv.getView().addEventListener('click', handler);
gv.getView().addEventListener('touchstart', handler);
同时,禁用一些交互动作和一些默认选中边框
// 选中边框为0
gv.getSelectWidth = function () { return 0; };
// 禁止鼠标缩放
gv.handleScroll = function () { };
// 禁止 touch 下双指缩放
gv.handlePinch = function () { };
// 禁止平移
gv.setPannable(false);
// 禁止框选
gv.setRectSelectable(false);
// 隐藏滚动条
gv.setScrollBarVisible(false);
// 2D 中所有节点不可拖动
gv.setMovableFunc(function () { return false; });
// 3D 中所有节点不可拖动
g3d.setMovableFunc(function () { return false; });
总结
通过 2D 3D 结合的方式的大屏展示,可以非常直观的看到数据呈现,比如在履带出的上料数据,通过它的位置,不需要太多文字描述就知道这里是要展示什么内容。HT 非常轻量,可以结合 2D 3D 呈现数据,矢量在各种屏幕下不失真,还可以适应各种屏幕大小进行展示,用来做大屏可视化再合适不过了。除了在大屏上,电脑上可以展示良好,移动端同样支持,最后放上一张移动端的效果图
基于 HTML5 的工业组态高炉炼铁 3D 大屏可视化的更多相关文章
- 基于 HTML5 的 WebGL 楼宇自控 3D 可视化监控
前言 智慧楼宇和人们的生活息息相关,楼宇智能化程度的提高,会极大程度的改善人们的生活品质,在当前工业互联网大背景下受到很大关注.目前智慧楼宇可视化监控的主要优点包括: 智慧化 -- 智慧楼宇是一个生态 ...
- 基于 B/S 端构建的 3D 楼宇自控可视化监控
前言 智慧楼宇和人们的生活息息相关,楼宇智能化程度的提高,会极大程度的改善人们的生活品质,在当前工业互联网大背景下受到很大关注.目前智慧楼宇可视化监控的主要优点包括: 智慧化 -- 智慧楼宇是一个生态 ...
- 基于 HTML5 的工业互联网 3D 可视化应用
工业企业中生产线处于高速运转,由工业设备所产生.采集和处理的数据量远大于企业中计算机和人工产生的数据,生产线的高速运转则对数据的实时性要求也更高.破解这些大数据就是企业在新一轮制造革命中赢得竞争力的钥 ...
- 基于 HTML5 WebGL 构建智能城市 3D 场景
前言 随着城市规模的扩大,传统的方式很难彻底地展示城市的全貌,但随着 3D 技术的应用,出现了 3D 城市群的方式以动态,交互式地把城市全貌呈现出来.配合智能城市系统,通过 Web 可视化的方式,使得 ...
- 基于HTML5的WebGL电信网管3D机房监控应用
先上段视频,不是在玩游戏哦,是规规矩矩的电信网管企业应用,嗯,全键盘的漫游3D机房: http://www.hightopo.com/guide/guide/core/3d/examples/exam ...
- 基于 HTML5 和 WebGL 的地铁站 3D 可视化系统
前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...
- 基于 HTML5 + WebGL 的宇宙(太阳系) 3D 可视化系统
前言 近年来随着引力波的发现.黑洞照片的拍摄.火星上存在水的证据发现等科学上的突破,以及文学影视作品中诸如<三体>.<流浪地球>.<星际穿越>等的传播普及,宇宙空间 ...
- 使用webgl(three.js)搭建3D智慧园区、3D大屏,3D楼宇,智慧灯杆三维展示,3D灯杆,web版3D,bim管理系统——第六课
前言: 今年是建国70周年,爱国热情异常的高涨,为自己身在如此安全.蓬勃发展的国家深感自豪. 我们公司楼下为庆祝国庆,拉了这样的标语,每个人做好一件事,就组成了我们强大的祖国. 看到这句话,深有感触, ...
- 基于 HTML5 的 WebGL 技术构建 3D 场景(一)
今天和大家分享的是 3D 系列之 3D 预定义模型. HT for Web 提供了多种基础类型供用户建模使用,不同于传统的 3D 建模方式,HT 的建模核心都是基于 API 的接口方式,通过 HT 预 ...
随机推荐
- DOM_xss预备知识
http://xuelinf.github.io/2016/05/18/%E7%BC%96%E7%A0%81%E4%B8%8E%E8%A7%A3%E7%A0%81-%E6%B5%8F%E8%A7%88 ...
- NGUI与特效的层级关系
通过调整特效的 render queue 来解决特效与NGUI界面之间的层级关系问题,用以下脚本解决: using System.Collections.Generic; using UnityEng ...
- 构建高性能的MYSQL数据库系统-主从复制
实验环境: DB1:172.16.1.100 DB2:172.16.1.101 VRRIP:172.16.1.99 步骤: yum -y install mysql 1.修改DB1的mysql配置文件 ...
- 平常比较多实用的SQL
创建数据库 创建之前判断该数据库是否存在 if exists (select * from sysdatabases where name='databaseName') drop database ...
- 详解Python变量在内存中的存储
这篇文章主要是对python中的数据进行认识,对于很多初学者来讲,其实数据的认识是最重要的,也是最容易出错的.本文结合数据与内存形态讲解python中的数据,内容包括: 引用与对象 可变数据类型与不可 ...
- git忽略某些文件的几种方法
不知道为什么我记得我写过这个内容但是又找不到了,只好照着大致记忆写一下以备留存. 1.首先肯定是.gitignore文件 .gitignore文件适合在文件尚未被追踪时加入,将其忽略便可以不上传到远程 ...
- 在HTML5的 input:file 上传文件类型控制 遇到的问题
1.input:file 属性的介绍 先瞅代码吧 <form> <input type="file" name="pic" accept=& ...
- flask框架----信号
一.实例化补充 instance_path和instance_relative_config是配合来用的.这两个参数是用来找配置文件的,当用app.config.from_pyfile('settin ...
- P4027 [NOI2007]货币兑换(斜率优化dp+cdq分治)
P4027 [NOI2007]货币兑换 显然,如果某一天要买券,一定是把钱全部花掉.否则不是最优(攒着干啥) 我们设$f[j]$为第$j$天时用户手上最多有多少钱 设$w$为花完钱买到的$B$券数 $ ...
- Python Redis set集合
Set操作.Set集合就是不允许重复的列表 (无序集合) sadd(name,values) # name对应的集合中添加元素 scard(name) # 获取name对应的集合中元素个数 sdiff ...