得益于 HTML5 WebGL 技术的成熟,从技术上对工控管理的可视化,数据可视化变得简单易行!完成对工控设备的管理效率,资源管理,风险管理等的大幅度提升,同时也对国家工业4.0计划做出有力响应!javascript
如本案例所示,是一个基于 HTML5 WebGL 技术实现的计量站三维可视化监控系统,在本案例中,具体宏观的展现一个油田站点的总体场景,而后点击能够进入内景看到油田计量站内景的具体状况,同时能够看到各个设备的参数的当前状态。java
一样的其中功能组件具备很高的复用性,因此也会很是方便的应用到其余场景中!json
以下所示,即是本案例运行动态图:dom
此项目连接:基于 HTML5 WebGL 的计量站三维可视化监控系统 Web 组态工控应用函数
(www.hightopo.com/demo/meteri… ) 动画
一、点击来回切换场景;ui
二、管线流动效果;spa
三、数据面板动态显示;3d
确认功能需求后就能够开始实施实现,动手实现以前要先确认场景有哪些,以下所示主要有油田外景和内景。code
外景:
本 demo 须要掌握 HT for Web 的 2d 和 3d 相关 技术,具体技术参考资料能够去 HT for Web 官网图扑软件了解。
一、 默认视角 在三维场景中,须要先设置一个默认视角,当从新打开页面时候直接回到默认视角,经过 setFar, setEye 和 setCenter 方法实现。
gv.setFar(100000);
gv.setEye([1247, 600, 1972]);
gv.setCenter([0, 0, 0]);
复制代码
二、 视角限制 因为三维场景的特性,若是不做出视角限制,就会出现穿模,翻底等现象,尤为本案例有天空球效果,若是不做出视角限制当用户无限拉远后会出现视角跑到天空球外,场景消失问题,这将会很是尴尬!
具体实现是经过 setEye 方法和 setCenter 方法控制场景的 eye 和 center 变量实现,放置到 mp 函数内。
mp(listener, scope, ahead); // 增长自身属性变化事件监听器
复制代码
// 限制 eye
gv.mp(function (e) {
if (e.property === 'eye') {
if (gv.getEye()[1] < 90) {
gv.getEye()[1] = 90;
}
if (gv.getEye()[1] > 1500) {
gv.getEye()[1] = 1500;
}
if (gv.getEye()[0] > 2400) {
gv.getEye()[0] = 2400;
}
if (gv.getEye()[0] < -2400) {
gv.getEye()[0] = -2400;
}
if (gv.getEye()[2] > 2500) {
gv.getEye()[2] = 2500;
}if (gv.getEye()[2] < -2400) {
gv.getEye()[2] = -2400;
}
}
})
复制代码
三、 点击切换场景 经过 mi 添加交互事件监听器为要点机交互模型绑定事件,经过 e.kind 判断点击事件,而后经过 tag 标签名获取要点击交互的模型对象。
首先在点击时候有个拉近效果和周围模型透明化效果,则是经过 flyTo 实现拉近效果和 setStyle 方法实现拉近后其余模型透明化。
具体代码以下:
gv.mi(function (e) {
if (e.kind === 'clickData') {
for (var i = 1; i <= 2; i++) {
if (e.data.getTag() === 'engineRoom' + i) {
// 点击拉近场景
gv.flyTo(e.data, {
animation: true,
distance: 500
});
// 选中模型实化
e.data.setStyle('shape3d.transparent', false);
e.data.setStyle('shape3d.opacity', 1);
// 其余模型透明化
dm.each(data => {
if (data.getTag() != 'engineRoom' + i) {
data.setStyle('shape3d.transparent', true);
data.setStyle('shape3d.opacity', 0.3);
data.setStyle('all.transparent', true);
data.setStyle('all.opacity', 0.5);
}
})
}
}
}
})
复制代码
实现效果以下:
场景切换的核心是经过 gv.deserialize() 反序列化显示路径对应场景,经过输入场景路径参数,在回调函数内完成场景渲染显示,代码以下:
gv.deserialize('scenes/油田.json', function (json, dm, gv, datas) {
if (json.title) document.title = json.title;
if (json.a['json.background']) {
var bgJSON = json.a['json.background'];
if (bgJSON.indexOf('displays') === 0) {
var bgGv = new ht.graph.GraphView();
bgGv.deserialize(bgJSON);
bgGv.addToDOM();
graphView.addToDOM(bgGv.getView());
}
else if (bgJSON.indexOf('scenes') === 0) {
var bgG3d = new ht.graph3d.Graph3dView();
bgG3d.deserialize(bgJSON);
bgG3d.addToDOM();
graphView.addToDOM(bgG3d.getView());
}
graphView.handleScroll = function () { };
}
})
复制代码
但在这以前有一个问题,就是如何处理当前场景和经过反序列化渲染显示场景的关系,若是不做处理,就会出现当前场景和要切换显示的场景重合问题,因此在点击切换场景过程当中,要先清空当前场景,为后来要切换的场景腾出地方。
因此在前面要先加一行代码:
dm.clear();
复制代码
作完处理后,如今是完成了切换过去效果,但还有要切换回来的功能,这个实现很是简单,取了个巧,直接 window.location.reload(); 刷新页面就好。
最终这部分完整代码以下:
function jump(position3d) {
var timer = setInterval(function () {
clearInterval(timer)
var distance = ht.Default.getDistance(gv.getEye(), position3d);
if (distance <= 501) {
var home = g2d.dm().getDataByTag('home');
home.s('2d.visible', true);
var line = g2d.dm().getDataByTag('line');
line.s('2d.visible', true);
dm.clear();
gv.deserialize('scenes/油田.json', function (json, dm, gv, datas) {
if (json.title) document.title = json.title;
if (json.a['json.background']) {
var bgJSON = json.a['json.background'];
if (bgJSON.indexOf('displays') === 0) {
var bgGv = new ht.graph.GraphView();
bgGv.deserialize(bgJSON);
bgGv.addToDOM();
graphView.addToDOM(bgGv.getView());
}
else if (bgJSON.indexOf('scenes') === 0) {
var bgG3d = new ht.graph3d.Graph3dView();
bgG3d.deserialize(bgJSON);
bgG3d.addToDOM();
graphView.addToDOM(bgG3d.getView());
}
graphView.handleScroll = function () { };
}
})
}
}, 500)
}
复制代码
我将它放置到 jump 函数内,而后将 jump 函数放到前面点击事件中调用,让代码总体简洁一些。
实现效果以下图:
首先效果以下图所示:
pipelineAnim(0.1)
function pipelineAnim(offset1) {
var anim1 = ht.Default.startAnim({
duration: 2000,
action: function () {
offset1 += 0.015;
var pipelines = gv.dm().getDataByTag('pipeline');
pipelines.setStyle('shape3d.uv.offset', [-offset1, 0]);
},
finishFunc: function () {
pipelineAnim(offset1);
}
})
}
复制代码
数据面板则是经过定时器在固定间隔时间循环执行赋予随机数便可,在这里经过随机数模拟真实数据,在实际当中是经过和后台对接实现真实数据动态变化,代码以下:
setInterval(function () {
for (var i = 1; i <= 4; i++) {
var panels = gv.dm().getDataByTag('panel' + i);
for (var j = 1; j <= 3; j++) {
if (panels.a('text' + j) != undefined) {
var num = parseFloat(Math.random() * (100 - 10 + 1) + 10, 10).toFixed(2);
var textJson = { "参数名": "出口温度", "参数值": num, "参数单位": panels.a('text' + j)['参数单位'] };
panels.a('text' + j, textJson);
}
}
}
}, 1000)
复制代码
以上即是我今天给你们带来的工控案例,但愿各位看官可以喜欢本 demo,在本案例中可以获得一些启发。