V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
xiangbulala
V2EX  ›  JavaScript

基于 WebGL 架构的 3D 可视化平台—三维设备管理(ThingJS 实现设备管理 3D 可视化)

  •  
  •   xiangbulala · 2018-12-14 14:14:15 +08:00 · 3136 次点击
    这是一个创建于 2173 天前的主题,其中的信息可能已经有所发展或是发生改变。

    国内高层建筑不断兴建,它的特点是高度高、层数多、体量大。面积可达几万平方米到几十万平方米。这些建筑都是一个个庞然大物,高高的耸立在地面上,这是它的外观,而随之带来的内部的建筑设备也是大量的。为了提高设备利用率,合理地使用能源,加强对建筑设备状态的监视等,自然地就提出了楼宇自动化控制系统。下面我们将用 ThingJS 平台来模拟一个设备管理系统。

    第一步,利用 CampusBuilder 搭建模拟场景。CampusBuilder 的模型库有各种各样的模型,使我们搭建出的场景更逼真。使用 CampusBuilde 创建层级,之后再给层级加外立面就出现了当前的效果。详情移步:CampusBuilder3D 场景制作工具

    先看结果:演示地址

    第二步,创建 Equipment 类,这里创建。switchControl 方法主要一个完成一个计时器的功能来模拟设备警报。

    class Equipment extends THING.Thing {
        constructor(app, name, obj, url) {
            super(app);
            this.name = name;
            this.obj = obj;
            this.url = url;
            this.interval = null;
            this.localPosition = [Math.floor(Math.random() * 7), 2.9, Math.floor(Math.random() * 7)];
        }
        createSelf() {
            app.create({
                type: 'Equipment',
                name: this.name,
                url: this.url,
                parent: this.obj,
                localPosition: this.localPosition,
                angle: 0
            });
        }
        switchControl(ev) {
            var flag;
            var equipment = app.query(this.name)[0];
            app.level.change(equipment);
            if (ev) {
                this.interval = setInterval(function () {
                    if (flag) {
                        equipment.style.color = '#FF0000';
                        flag = false;
                    } else {
                        flag = true;
                        equipment.style.color = '';
                    }
                }, 500);
                console.log(this.interval + "查看是否创建了定时器");
            } else {
                console.log(this.interval);
                clearInterval(this.interval);
                if (equipment.style.color == '#FF0000')
                    equipment.style.color = '';
            }
        }
    }
    THING.factory.registerClass('Equipment', Equipment);
    

      第三步,创建摄像机面板,烟感报警面板以及控制设备的开关,这里简单调整一下面板位置之后会增加两个创建设备的按钮。

    //创建主面板
    var panel1 = new THING.widget.Panel({
        titleText: '摄像机列表',
        closeIcon: false, // 是否有关闭按钮
        dragable: true,
        retractable: true,
        opacity: 0.9,
        hasTitle: true,
    });
    panel1.position = [80, 0];
    

    var panel2 = new THING.widget.Panel({ titleText: '烟感报警列表', closeIcon: false, // 是否有关闭按钮 dragable: true, retractable: true, opacity: 0.9, hasTitle: true, }); panel2.position = [80, 320];

    // 创建任意对象 var dataObj1 = { open1: false, open2: false, open3: false, open4: false, } var dataObj2 = { open5: false, open6: false, open7: false, open8: false, };

    // 动态绑定物体 var open1 = panel1.addBoolean(dataObj1, 'open1').caption('设备 01'); var open2 = panel1.addBoolean(dataObj1, 'open2').caption('设备 02'); var open3 = panel1.addBoolean(dataObj1, 'open3').caption('设备 03'); var open4 = panel1.addBoolean(dataObj1, 'open4').caption('设备 04'); var open5 = panel2.addBoolean(dataObj2, 'open5').caption('设备 01'); var open6 = panel2.addBoolean(dataObj2, 'open6').caption('设备 02'); var open7 = panel2.addBoolean(dataObj2, 'open7').caption('设备 03'); var open8 = panel2.addBoolean(dataObj2, 'open8').caption('设备 04');

      第四步,开启场景层级切换,创建摄像机和烟感报警器各四个,创建一个数字标识 index 和保存 equipment 对象的数组 equipmentGroup。

    //创建 equipment 对象数组,以及数组标识
    var equipmentGroup = [];
    var index = 0;
    

    app.on('load', function (ev) {

    app.level.change(ev.campus);
    
    for (var i = 0; i < 8; i++) {
        var type = null;
        if (i < 4) {
            type = 'http://model.3dmomoda.cn/models/62A8A75C75044E6AB3D8463FA0CB67AF/0/gltf/';
        } else {
            type = 'http://model.3dmomoda.cn/models/641A9B800DE5431E8C84DC290F8EFDE6/0/gltf/';
        }
        var equipment = new Equipment(app, 'equipment' + index++, app.query('floor' + (Math.floor(Math.random() * 5) + 1))[0], type);
        equipment.createSelf();
        equipmentGroup.push(equipment);
    }
    

    });

      第五步,为每个设备对应的创建控制开关。

    open1.on('change', function (ev) {
            equipmentGroup[0].switchControl(ev);
        });
        open2.on('change', function (ev) {
            equipmentGroup[1].switchControl(ev);
        });
        open3.on('change', function (ev) {
            equipmentGroup[2].switchControl(ev);
        });
        open4.on('change', function (ev) {
            equipmentGroup[3].switchControl(ev);
        });
        open5.on('change', function (ev) {
            equipmentGroup[4].switchControl(ev);
        });
        open6.on('change', function (ev) {
            equipmentGroup[5].switchControl(ev);
        });
        open7.on('change', function (ev) {
            equipmentGroup[6].switchControl(ev);
        });
        open8.on('change', function (ev) {
            equipmentGroup[7].switchControl(ev);
        });
    

      最后一步,创建两个按钮来控制创建设备。

    new THING.widget.Button('创建烟感报警', function () {
        var type = 'http://model.3dmomoda.cn/models/641A9B800DE5431E8C84DC290F8EFDE6/0/gltf/';
        var equipment = new Equipment(app, 'equipment' + index++, app.query('floor' + (Math.floor(Math.random() * 5) + 1))[0], type,);
        equipment.createSelf();
        equipmentGroup.push(equipment);
        app.level.change(app.query(equipment.name)[0]);
    });
    

    new THING.widget.Button('创建摄像头', function () { var type = 'http://model.3dmomoda.cn/models/62A8A75C75044E6AB3D8463FA0CB67AF/0/gltf/'; var equipment = new Equipment(app, 'equipment' + index++, app.query('floor' + (Math.floor(Math.random() * 5) + 1))[0], type,); equipment.createSelf(); equipmentGroup.push(equipment); app.level.change(app.query(equipment.name)[0]); });

      

    在编写过程还是走了不少弯路的,最主要的就是计时器的卸载问题,最初的版本写来写去发现不能控制警报的关闭,后来才 发现计时器没有卸载,警报不但不会关闭而且闪动的频率越来越快。更改之后创建了 Equipment 这个类来控制所有设备,通过创建这个类的对象给他赋 id,父物体,模型地址。这里控制器在开关被触发的时候创建一个新的计时器并赋给的这个对象,再次触发时清除这个计时器,警报的动画就关闭了。演示地址

    6 条回复    2018-12-15 13:58:10 +08:00
    Woodywuuu
        1
    Woodywuuu  
       2018-12-14 14:34:05 +08:00
    眼花了下还以为是 three.js
    xiangbulala
        2
    xiangbulala  
    OP
       2018-12-14 15:12:49 +08:00
    @Woodywuuu 哈哈哈 像写 jq 一样写 three.js
    feelapi
        3
    feelapi  
       2018-12-14 21:31:18 +08:00
    不错的思路,可惜没有场景优化,模型大了之后比较慢。
    qile1
        4
    qile1  
       2018-12-15 12:16:30 +08:00 via Android
    这个是不是可以应用到服务器监控上面,监测硬盘状态,网卡状态,web 服务状态等,实现可视化,这个收费是怎么收费?
    xiangbulala
        5
    xiangbulala  
    OP
       2018-12-15 13:54:46 +08:00
    @feelapi
    这只是简单演示,大场景是要动态加载的
    xiangbulala
        6
    xiangbulala  
    OP
       2018-12-15 13:58:10 +08:00
    @qile1 对,公司最开始就是做数据中心可视化的,thingjs 是基于 three.js 分装,让没有 three.js 工程师的公司也能像写 js 一样做 3D 可视化,专门的数据中心可视化产品介绍可以看这个链接:[数据中心可视化]( http://www.uinnova.cn/product/tarsier/ovc/dcv)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5543 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 09:24 · PVG 17:24 · LAX 01:24 · JFK 04:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.