基于 HTML WebGL 的会展中心智能监控系统
前言
随着近几年物联网、万物互联等诸多概念的大行其道,智慧城市的概念也早已经被人们耳熟能详,而作为城市的组成部分,智慧建筑也是重中之重,智慧园区,智慧小区等也如雨后春笋般的相继出现。
智慧建筑是指通过将建筑物的结构、系统、服务和管理根据用户的需求进行最优化组合,从而为用户提供一个高效、舒适、便利的人性化建筑环境,智慧建筑绝不仅仅只是智慧园区、智慧小区这种模式,这里我就通过 HT for Web 制作了一个以会展中心为主体的智慧建筑监控系统。
效果预览
代码实现
场景呈现
通过上面的效果预览,可以分辨出整个监控系统是分为 3 个层次的,分别是主体、楼内、展厅,如果是使用单个 graph3dView
加载所有场景,通过 dm.clear()
清除场景,dm.deserieialize()
加载新场景这种切换方式必然会有一个极短的渲染时间,使切换时不连贯,所以我这里就使用了 3 个 graph3dView
,去呈现各自的层级模型,通过 notifier
事件通知器监听场景切换,代码如下:
notifier.add((event) => {
if (event.kind === 'sceneChange') {
const oldSceneKey = event.oldScene,
newSceneKey = event.newScene,
oldScene = G[oldSceneKey],
newScene = G[newSceneKey];
oldScene.removeFromDOM();
newScene.addToDOM();
if (newScene.graph2d.isAnimed) {
newScene.graph3d.animByList();
} else {
newScene.graph3d.animByList(newScene.graph2d.animByList, newScene.graph2d);
}
}
});
其中 removeFromDOM
是自行封装的一个方法
removeFromDOM() {
const g3d = this.g3d,
view = g3d.getView();
if (view.remove) {
view.remove()
} else {
view.parentNode.removeChild(view)
}
this.notifier.fire({
kind: 'reset',
});
}
但是这样还是有一个问题,graph3dView
默认如果不放到页面中,场景中的 obj
等模型相关资源是不会请求和渲染的,这样对性能是十分友好的,但是当我第一次切换场景时,还是会有短暂的请求和渲染时间,所以这里我需要对资源进行预加载。
资源预加载
这里我通过在 body
中添加一个不在窗口展示的与窗口等宽高的 div
元素,通过把当前不展示的 graph3dView
放到其中触发对相应 obj
等模型资源的请求和渲染,完成预加载,代码如下:
const preloadDiv = document.createElement('div');
preloadDiv.style.position = 'absolute';
preloadDiv.style.bottom = '100%';
preloadDiv.style.width = '100%';
preloadDiv.style.height = '100%';
document.body.appendChild(preloadDiv);
scene2.addToDOM(preloadDiv);
scene3.addToDOM(preloadDiv);
模型加载完成后再执行动画
web 页面加载是依赖网速的,会展中心模型 obj
等资源文件是有一定大小的,可能对于不同带宽网速的用户所需要加载的时间也不尽相同,这里就需要判断下 obj
是否全部加载完成,加载完成后再执行动画效果,通过 ht.Default.handleModelLoaded
监控是否所有模型都请求加载完成, 加载完成后开始执行动画,顺便释放之前预加载的 graph3dView
,代码如下:
let modelSize = 0;
ht.Default.handleModelLoaded = (name, model) => {
modelSize++;
if (modelSize === 62) {
scene1.graph3d.enableShadow();
scene3.graph3d.enableShadow();
scene2.removeFromDOM();
scene3.removeFromDOM();
scene1.graph3d.animByList(scene1.graph2d.animByList, scene1.graph2d);
}
};
动画依参数顺序执行
我想要场景第一次加载时,视角拉近后左右两边的面板再一点一点的加载出来,动画效果是不完全线性顺序的去执行,所以我这里通过 ht.Default.startAnim
方法封装了一套通过参数数组进行的动画的方法,代码如下:
animByList(callback, obj) {
this.isAnimed = true;
const animList = this.animList,
self = this;
let callAnim = (ind) => {
const param = animList.get(ind);
param && self.anim(param, () => {
callAnim(ind + 1);
const lastParam = animList.get(ind + 1);
lastParam || callback && callback.call(obj || this);
});
};
callAnim(0);
}
anim(animParam, callback) {
const self = this,
time = animParam['time'] || 1000,
easing = animParam['easing'] || function (t) {
return t * t;
},
func = animParam['func'];
this.__animObj = ht.Default.startAnim({
duration: time || 1000,
easing: easing,
action: function (v, t) {
const V = v,
T = t;
function animFunc(param) {
let v = V,
t = T;
if (param instanceof Function) {
param(v, t);
} else {
const type = param['type'],
object = param['object'],
objectTag = param['objectTag'],
key = param['key'],
oldValue = param['oldValue'],
newValue = param['newValue'],
oneTime = param['time'],
scope = param['scope'];
if (scope) {
v = v < scope[0] ? 0 : v > scope[1] ? 1 : (v - scope[0]) / (scope[1] - scope[0]);
} else {
v = !oneTime || oneTime > time ? v : v * time / oneTime < 1 ? v * time / oneTime : 1;
}
let obj, value;
obj = object ? object : objectTag ? self.view.dm().getDataByTag(objectTag) : undefined;
if (!obj) return;
if (!isSameType(oldValue, newValue) || !isNumORNumArray(oldValue)) return;
if (oldValue instanceof Array) {
if (oldValue.length !== newValue.length) return;
const darr = newValue.map((n, i) => {
return n - oldValue[i];
});
value = oldValue.map((n, i) => {
return n + darr[i] * v;
});
} else {
const d = newValue - oldValue;
value = oldValue + d * v;
}
ht.Default.setPropertyValue(obj, type, key, value);
}
}
if (animParam instanceof Array) {
animParam.forEach(ele => {
animFunc(ele);
});
} else {
animFunc(animParam);
}
},
finishFunc: function () {
func && func(func);
callback && callback();
},
});
}
参数格式如下:
// 视角移动
param = {
object: g3d,
type: undefined,
key: 'eye',
oldValue: [-118, 5130, 15858],
newValue: [-26, 1130, 3494],
time: 1000,
}
animList.add();
// 标题从左到右出现
param = {
object: title,
type: 'style',
key: 'clip.percentage',
oldValue: 0,
newValue: 1,
time: 1500,
};
animList.add(param);
可点击部分高亮效果
为了突出可以点击的部分,我加了高亮效果,设置鼠标悬浮高亮模式,并通过 g3d.getHighlightHelper().setFetchTargetFunc
方式筛选需要鼠标高亮的图元,代码如下:
g3d.setHighlightMode('mouseover');
g3d.getHighlightHelper().setFetchTargetFunc(function (nodes) {
let sortList = new ht.List(nodes);
return sortList.toArray(node => {
return jumpList.contains(node);
});
});
楼层视角跳转
因为整体的楼层比较大,而每个楼层中可选择的展区又比较小,所以这里我做了一个视角调整,可以使用单独移动视角到正视相应楼层的视角 flyTo
,这里除了采用右侧边栏选中移动,也做了鼠标移入相应楼层右键改变视角的处理,使用了新建的类 messageView
做交互提示。
g3d.flyTo(floor, {
animation: true,
direction: [0, 1, 2],
center: floor.p3().map((n, i) => {
return i !==1 ? n : n + floor.getTall() / 2;
}),
distance: distances[newFloor - 1],
});
总结
随着科技的井喷式发展,智慧建筑将如雨后春笋般崛起,其应用的场景也会不断拓展,应运而生的数据可视化管理系统也应该配套升级,为其把数字信息变为直观的、以图形图像信息表示的信息,清晰的展现在客户的面前,这将是无可阻挡的时代大趋势。
还有更多的可视化案例可以参考:https://www.hightopo.com/demos/index.html
基于 HTML WebGL 的会展中心智能监控系统的更多相关文章
- 基于 HTML5 WebGL 的地铁站 3D 可视化系统
前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...
- 基于 HTML5 + WebGL 实现 3D 可视化地铁系统
前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...
- 基于 HTML5 + WebGL 的地铁 3D 可视化系统
前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...
- 基于 H5 + WebGL 实现 3D 可视化地铁系统
前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...
- 基于 HTML5 WebGL 的发动机 3D 可视化系统
前言 工业机械产品大多体积庞大.运输成本高,在参加行业展会或向海外客户销售时,如果没有实物展示,仅凭静态.简单的图片说明书介绍,无法让客户全面了解产品,不仅工作人员制作麻烦,客户看得也费力.如 ...
- 基于 HTML5 WebGL 的智慧楼宇可视化系统
前言 可视化的智慧楼宇在 21 世纪是有急迫需求的,中国被世界称为"基建狂魔",全球高层建筑数量位居首位,所以对于楼宇的监控是必不可少.智慧楼宇可视化系统更多突出的是管理方面的功能 ...
- 基于 HTML5 WebGL 的虚拟现实可视化培训系统
前言 2019 年 VR, AR, XR, 5G, 工业互联网等名词频繁出现在我们的视野中,信息的分享与虚实的结合已经成为大势所趋,5G 是新一代信息通信技术升级的重要方向,工业互联网是制造业转型升级 ...
- 基于 HTML5 WebGL 的高炉炼铁厂可视化系统
前言 在当今 工业4.0 新时代的推动下,不仅迎来了 工业互联网 的发展,还开启了 5G 时代的新次元.而伴随着带宽的提升,网络信息飞速发展,能源管控上与实时预警在工业互联网中也占着举足轻 ...
- 基于 HTML5 WebGL 的 水泥工厂可视化系统
前言 如今的制造行业,基于数据进行生产策略制定与管理已经成为一种趋势,特别是 工业4.0 的浪潮下,数据战略已经成为很多制造企业的优先战略,而数据可视化以更直观的方式,帮助指导决策,成为数据分析传递信 ...
随机推荐
- Spring ioc xml 实例化bean 自己实现
public class DefClassPathXmlApplicationContext { private String xmlPath; public DefClassPathXmlAppli ...
- [React]Hook初探
Hook是什么 Hook是React从16.8开始支持的特性,使用Hook可以在不使用class时使用state Hook支持在不需要修改组件状态的情况下复用逻辑状态,从而解决使用render pro ...
- 不可被忽视的操作系统( FreeRTOS )【1】
把大多数人每个星期的双休过过成了奢侈的节假日放假,把每天23点后定义为自己的自由时间,应该如何去思考这个问题 ? 双休的两天里,不!是放假的两天里,终于有较长的时间好好的学习一下一直断断续续的Free ...
- python之xlrd和xlwt模块读写excel使用详解
一.xlrd模块和xlwt模块是什么 xlrd模块是python第三方工具包,用于读取excel中的数据: xlwt模块是python第三方工具包,用于往excel中写入数据: 二 ...
- 在vue项目中使用md5加密 sirai
1.安装模块 npm install js-md5 -D 2.在项目中引入模块 import md5 from 'js-md5' 3.把你需要加密的信息进行前期处理 CalcuMD5 = functi ...
- 微信小程序--分享功能
微信小程序--分享功能 微信小程序前段时间开放了小程序右上角的分享功能, 可以分享任意一个页面到好友或者群聊, 但是不能分享到朋友圈 这里有微信开发文档链接:点击跳转到微信分享功能API 入口方法: ...
- 批处理 bat 查询局域网内在线电脑IP
查看自己局域网的IP和物理网卡地址可以在 WIN+R –> 打开cmd 键入 arp -a 可以看到局域网中所有的在线IP COLOR 0A CLS @ECHO Off Title 查询局域网内 ...
- VUE_shop(第十天)项目的打包优化
项目的打包优化 1.添加页面的加载效果 1.首先安装运行依赖nprocess,在main.js文件中的axios拦截器拦截请求的时候调用Npeocees.start. 在拦截响应的时候调用nproce ...
- linux如何杀死指定进程
ps aux | grep '进程名称' sudo kill pid
- Linux kernel min/max宏
#define min(x,y) ({ \ typeof(x) _x = (x); \ typeof(y) _y = (y); \ (void) (&_x == &_y); \ _x ...