欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

基于 HTML5 WebGL 的计量站三维可视化监控系统 Web 组态工控应用

程序员文章站 2022-11-27 15:07:54
得益于 HTML5 WebGL 技术的成熟,从技术上对工控管理的可视化,数据可视化变得简单易行!完成对工控设备的管理效率,资源管理,风险管理等的大幅度提高,同时也对国家工业4.0计划作出有力响应! 如本案例所示,是一个基于 HTML5 WebGL 技术实现的计量站三维可视化监控系统,在本案例中,具... ......

得益于 html5 webgl 技术的成熟,从技术上对工控管理的可视化,数据可视化变得简单易行!完成对工控设备的管理效率,资源管理,风险管理等的大幅度提高,同时也对国家工业4.0计划作出有力响应!

如本案例所示,是一个基于 html5 webgl 技术实现的计量站三维可视化监控系统,在本案例中,具体宏观的展示一个油田站点的整体场景,然后点击可以进入内景看到油田计量站内景的具体情况,同时可以看到各个设备的参数的当前状态。

同样的其中功能组件具有很高的复用性,所以也会非常方便的应用到其他场景中!

如下所示,便是本案例运行动态图:

此项目链接:基于 html5 webgl 的计量站三维可视化监控系统 web 组态工控应用

()

基于 HTML5 WebGL 的计量站三维可视化监控系统 Web 组态工控应用

在这个场景中主要有如下几个功能:

1、点击来回切换场景;

2、管线流动效果;

3、数据面板动态显示;

确认功能需求后就可以开始实施实现,动手实现之前要先确认场景有哪些,如下所示主要有油田外景和内景。

外景:

基于 HTML5 WebGL 的计量站三维可视化监控系统 Web 组态工控应用

内景:

基于 HTML5 WebGL 的计量站三维可视化监控系统 Web 组态工控应用

技能储备

本 demo 需要掌握 ht for web 的 2d 和 3d 相关 技术,具体技术参考资料可以去 ht for web 官网了解。

实现功能

1、默认视角

在三维场景中,需要先设置一个默认视角,当重新打开页面时候直接回到默认视角,通过 setfar , seteye 和 setcenter 方法实现。

gv.setfar(100000);
gv.seteye([1247, 600, 1972]);
gv.setcenter([0, 0, 0]);

2、视角限制

由于三维场景的特性,如果不作出视角限制,就会出现穿模,翻底等现象,尤其本案例有天空球效果,如果不作出视角限制当用户无限拉远后会出现视角跑到天空球外,场景消失问题,这将会非常尴尬!

具体实现是通过 seteye 方法和 setcenter 方法控制场景的 eye 和 center 变量实现,放置到 gv.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;
        }
    }
})

3、点击切换场景

通过 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);
                    }
                })
            }
        }
    }
})

实现效果如下:

基于 HTML5 WebGL 的计量站三维可视化监控系统 Web 组态工控应用

然后在完成拉近场景和透明化其他模型后,开始搞场景切换效果。

场景切换的核心是通过 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 函数放到前面点击事件中调用,让代码整体简洁一些。

实现效果如下图:

基于 HTML5 WebGL 的计量站三维可视化监控系统 Web 组态工控应用

4、管线流动效果和动态数据面板

最后两个功能实现非常简单,我就放到一块来说。

首先效果如下图所示:

基于 HTML5 WebGL 的计量站三维可视化监控系统 Web 组态工控应用

管线流动效果的实现核心就是控制 uv 贴图偏移,所以通过动画控制器 startanim 控制 uv 贴图偏移量就可以实现,在动画结束时,在 finishfunc 内回调函数即可实现动画循环。

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,在本案例中能够得到一些启发。