基于WebGL架构的3D可视化平台ThingJS-搭建设备管理系统
国内高层建筑不断兴建,它的特点是高度高、层数多、体量大。面积可达几万平方米到几十万平方米。这些建筑都是一个个庞然大物,高高的耸立在地面上,这是它的外观,而随之带来的内部的建筑设备也是大量的。为了提高设备利用率,合理地使用能源,加强对建筑设备状态的监视等,自然地就提出了楼宇自动化控制系统。下面我们将用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-搭建设备管理系统的更多相关文章
- 基于WebGL架构的3D可视化平台—设备管理
---恢复内容开始--- 国内高层建筑不断兴建,它的特点是高度高.层数多.体量大.面积可达几万平方米到几十万平方米.这些建筑都是一个个庞然大物,高高的耸立在地面上,这是它的外观,而随之带来的内部的建筑 ...
- 基于WebGL架构的3D可视化平台—新风系统演示
新风系统是根据在密闭的室内一侧用专用设备向室内送新风,再从另一侧由专用设备向室外排出,在室内会形成“新风流动场”,从而满足室内新风换气的需要.实施方案是:采用高风压.大流量风机.依靠机械强力由一侧向室 ...
- 基于WebGL架构的3D可视化平台—实现小车行走路线演示
小车行走路线演示New VS Old 刚接触ThingJS的时候,写的一个小车开进小区的演示,今天又看了教程中有movePath这个方法就重新写了一遍,其中也遇到了一些问题,尤其突出的问题就是小车过弯 ...
- 基于 HTML5 WebGL 的发动机 3D 可视化系统
前言 工业机械产品大多体积庞大.运输成本高,在参加行业展会或向海外客户销售时,如果没有实物展示,仅凭静态.简单的图片说明书介绍,无法让客户全面了解产品,不仅工作人员制作麻烦,客户看得也费力.如 ...
- 基于 HTML5 WebGL 的地铁站 3D 可视化系统
前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...
- 基于 HTML5 的 WebGL 楼宇自控 3D 可视化监控
前言 智慧楼宇和人们的生活息息相关,楼宇智能化程度的提高,会极大程度的改善人们的生活品质,在当前工业互联网大背景下受到很大关注.目前智慧楼宇可视化监控的主要优点包括: 智慧化 -- 智慧楼宇是一个生态 ...
- 基于 HTML5 WebGL 的挖掘机 3D 可视化应用
前言 在工业互联网以及物联网的影响下,人们对于机械的管理,机械的可视化,机械的操作可视化提出了更高的要求.如何在一个系统中完整的显示机械的运行情况,机械的运行轨迹,或者机械的机械动作显得尤为的重要,因 ...
- 基于 HTML5 WebGL 的加油站 3D 可视化监控
前言 随着数字化,工业互联网,物联网的发展,我国加油站正向有人值守,无人操作,远程控制的方向发展,传统的人工巡查方式逐渐转变为以自动化控制为主的在线监控方式,即采用数据采集与监控系统 SCADA.SC ...
- 基于 HTML5 和 WebGL 的地铁站 3D 可视化系统
前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...
随机推荐
- 结对编程core_6
林静雯PB16060913 李鑫PB16061107 对于这种结对的工作,由于有过电子设计实践的基础,大概知道建一个工程需要做的事,有点经验还是有帮助的. 一.问题要求: 1·主要功能是随机产生有效的 ...
- 友善RK3399/NanoPC-T4开发板wiringPi Python库访问GPIO外设实例讲解 -【申嵌视频】
1 wiringPi for Python简介 wiringPi for Python是wiringPi的Python语言扩展,用于在Python程序中操作GPIO/I2C/SPI库/UART/PWM ...
- 【C++】反斜杠“\”的作用
转自 https://blog.csdn.net/ismallboy/article/details/8082514 转义字符:如:\n表示回车+换行等. 续行符:这个需要注意一下,在一般的语句中,这 ...
- Asynchronous programming in javascript
Javascript是单线程的,因此异步编程对其尤为重要. ES 6以前: * 回调函数* 事件监听(事件发布/订阅)* Promise对象 ES 6: * Generator函数(协程corouti ...
- Linux下如何查看进程准确启动时间
- Apartment 2019
Apartment 2019 最近在学习3D建模,Apartment 2019是我的个人项目. 初步的想法是,先在网上找公寓建筑的平面图以及室内效果照片,根据这些参考图像来练习建模与渲染. 建模顺序与 ...
- Docker使用Link与newwork在容器之间建立连接
一,使用 --link容器互联 docker 默认使允许container 互通的(通过-icc=false 关闭互通)同一个宿主机上的多个docker容器之间如果想进行通信,可以通过使用容器的ip地 ...
- solidworks的工程图模板文件和图纸格式文件
工程图模板文件:drwdot,这个文件是在新建工程图的时候,可以选择的,如下. 图纸格式文件:slddrt,这个文件是进入工程图环境,编辑[图纸属性]的时候,可以选择的.如下. 怎么定制上述两种文件? ...
- 三个线程,ABC 10次(volatile+synchronized(2 synchronized可以保证内存可见性,所以去掉status 的volatile修饰符)
package ThreadABC; public class MyThread extends Thread { public static int status = 0; @Override pu ...
- 利用jvisualvm使用btrace进行线上调试案例
用途:btrace主要用于线上调试.通过btrace,可在不改动代码的前提下,方便的发现以下问题: 1.定位性能慢的接口服务: 2.实时打印堆栈信息,定位死锁位置: 3.定位占用大量内存空间的代码块: ...