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

第一步,利用CampusBuilder搭建模拟场景。CampusBuilder的模型库有各种各样的模型,使我们搭建出的场景更逼真。使用CampusBuilder创建层级,之后再给层级加外立面就出现了当前的效果。详情移步: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,父物体,模型地址。这里控制器在开关被触发的时候创建一个新的计时器并赋给的这个对象,再次触发时清除这个计时器,警报的动画就关闭了。演示地址

最后附上完整代码:

/**
 * 说明:创建App,url为场景地址(可选)
 */
var app = new THING.App({
    url: "http://www.thingjs.com/./uploads/wechat/oLX7p05lsWJZUIxnIWsNXAzJ40X8/scene/CampusBuilder20181126134710",    // 场景地址
    "skyBox": "BlueSky"
});

//创建主面板
var panel1 = new THING.widget.Panel({
    titleText: '设备列表',
    closeIcon: false, // 是否有关闭按钮
    dragable: true,
    retractable: true,
    opacity: 0.9,
    hasTitle: true,
    titleImage: 'https://www.thingjs.com/static/images/example/icon.png'
});
panel1.position = [80, 0];

var panel2 = new THING.widget.Panel({
    titleText: '设备列表',
    closeIcon: false, // 是否有关闭按钮
    dragable: true,
    retractable: true,
    opacity: 0.9,
    hasTitle: true,
    titleImage: 'https://www.thingjs.com/static/images/example/icon.png'
});
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');

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对象数组,以及数组标识
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);
    });

});

class Equipment extends THING.Thing {
    constructor(app, name, obj, url) {
        super(app);
        this.name = name;
        this.obj = obj;
        this.url = url;
        this.interval = null;
    }
    createSelf() {
        app.create({
            type: 'Equipment',
            name: this.name,
            url: this.url,
            parent: this.obj,
            localPosition: [Math.floor(Math.random() * 7), 2.9, Math.floor(Math.random() * 7)],
            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);

基于WebGL架构的3D可视化平台ThingJS-搭建设备管理系统的更多相关文章

  1. 基于WebGL架构的3D可视化平台—设备管理

    ---恢复内容开始--- 国内高层建筑不断兴建,它的特点是高度高.层数多.体量大.面积可达几万平方米到几十万平方米.这些建筑都是一个个庞然大物,高高的耸立在地面上,这是它的外观,而随之带来的内部的建筑 ...

  2. 基于WebGL架构的3D可视化平台—新风系统演示

    新风系统是根据在密闭的室内一侧用专用设备向室内送新风,再从另一侧由专用设备向室外排出,在室内会形成“新风流动场”,从而满足室内新风换气的需要.实施方案是:采用高风压.大流量风机.依靠机械强力由一侧向室 ...

  3. 基于WebGL架构的3D可视化平台—实现小车行走路线演示

    小车行走路线演示New VS Old 刚接触ThingJS的时候,写的一个小车开进小区的演示,今天又看了教程中有movePath这个方法就重新写了一遍,其中也遇到了一些问题,尤其突出的问题就是小车过弯 ...

  4. 基于 HTML5 WebGL 的发动机 3D 可视化系统

    前言     工业机械产品大多体积庞大.运输成本高,在参加行业展会或向海外客户销售时,如果没有实物展示,仅凭静态.简单的图片说明书介绍,无法让客户全面了解产品,不仅工作人员制作麻烦,客户看得也费力.如 ...

  5. 基于 HTML5 WebGL 的地铁站 3D 可视化系统

    前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...

  6. 基于 HTML5 的 WebGL 楼宇自控 3D 可视化监控

    前言 智慧楼宇和人们的生活息息相关,楼宇智能化程度的提高,会极大程度的改善人们的生活品质,在当前工业互联网大背景下受到很大关注.目前智慧楼宇可视化监控的主要优点包括: 智慧化 -- 智慧楼宇是一个生态 ...

  7. 基于 HTML5 WebGL 的挖掘机 3D 可视化应用

    前言 在工业互联网以及物联网的影响下,人们对于机械的管理,机械的可视化,机械的操作可视化提出了更高的要求.如何在一个系统中完整的显示机械的运行情况,机械的运行轨迹,或者机械的机械动作显得尤为的重要,因 ...

  8. 基于 HTML5 WebGL 的加油站 3D 可视化监控

    前言 随着数字化,工业互联网,物联网的发展,我国加油站正向有人值守,无人操作,远程控制的方向发展,传统的人工巡查方式逐渐转变为以自动化控制为主的在线监控方式,即采用数据采集与监控系统 SCADA.SC ...

  9. 基于 HTML5 和 WebGL 的地铁站 3D 可视化系统

    前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...

随机推荐

  1. Sublime Text3 离线安装Package Control并使用GBK编码 --转自https://blog.csdn.net/swhard/article/details/78930371

    1.关闭Sublime Text 3,去https://github.com/wbond/package_control/releases下载一个zip包,我下载的是 2.将包内的顶层文件夹解压至C: ...

  2. 工控随笔_18_西门子_WinCC的VBS脚本_07_变量作用域和传值、传址

    在vbs脚本中也存在和其他编程语言一样的概念,那就是变量的作用域,变量的作用域决 定在什么范围内可以访问. 同样的在vbs脚本中对于变量也有一个生命周期, 变量的生命周期决定了变量的存续时间 这个主要 ...

  3. 前后台数据交换,printwriter、jsonobject、jsonarray、ajax请求,数据交换

    后台代码: public void findByIDEquipment() { getResponse().setCharacterEncoding("UTF-8"); getRe ...

  4. Node文件模块

    在上一篇文章中有提到,Node模块分为核心模块和文件模块,接下来就简单总结一下文件模块. 文件模块则是在运行时动态加载,需要完整的路径分析.文件定位.编译执行过程.速度相比核心模块稍微慢一些,但是用的 ...

  5. Selenium常用方法

    Selenium是一个自动化测试工具,利用它可以驱动浏览器执行特定的动作,如点击.下拉等操作,同时还可以获取浏览器当前呈现的页面的源代码,做到可见即可爬.对于一些JavaScript动态渲染的页面来说 ...

  6. [UE4]让箭头保持水平的第二种方法:Combinrotators、Delta(Rotator)

    一.手柄在世界坐标系中有一个绝对朝向,我们可以知道箭头相对于手柄的朝向,相对于手柄的旋转角度. 可以通过手柄绝对朝向.箭头的相对于手柄的朝向计算得到箭头的绝对朝向. 在得到箭头的相对于手柄的角度,在这 ...

  7. 禅知Pro 1.6 前台任意文件读取 | 代码审计

    禅知 Pro v1.6 前台任意文件读取 | 代码审计 蝉知专业版是基于蝉知企业门户系统开源版开发,继承了蝉知本身的优秀功能.相对于蝉知开源版增强了商品的属性自定义.属性价格定制.物流跟踪.微信支付. ...

  8. 用yum快速搭建LAMP平台

    实验环境: [root@nmserver-7 html]# cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core) [root@nms ...

  9. day3-三级目录

    date = {"guangdong":{"guangzhou":{"tianhe":["tyx","zjxc ...

  10. C&C++类型定义typedef

    1.声明 1.1结构声明: struct { int n; double x,y; }; 1.2带结构标志的声明 struct point{ double x,y; }; 1.3定义结构类型 1.3. ...