基于 HTML5 WebGL 的楼宇智能化集成系统(三)



// 通过 moveCamera 改变 eye 和 center 来移动场景视角为大楼的正视面
moveCamera(g3d, [134, 399, 1617], [7, 40, 144], {
duration: 2000,
easing: t => t * t,
finishFunc: () => {
// 开启场景大楼模型的可透明为 true
this.building.eachChild(c => {
c.s({
'shape3d.transparent': true,
});
});
// 大楼模型线框的颜色变化
tweenColor(this.building, 'wf.color', 'rgba(72,149,232,1)', 'rgba(56,156,255,0.03)', {
duration: 2000,
easing: t => t
});
// 大楼模型整体染色的颜色变化
tweenColor(this.building, 'shape3d.blend', 'rgba(120,180,255,1)', 'rgba(120,180,255,0)', {
duration: 2000,
easing: t => t,
finishFunc: () => {
// 楼层设置为可见
this.floor.eachChild(c => {
setNodeVisible(c, true);
});
this.floorLighting = 1;
// 显示大楼建筑信息的动画
this.showBuilding();
}
});
}
});
- node:改变颜色的图元节点;
- startColor:起始颜色的 rgba 值;
- endColor:变化后颜色的 rgba 值;
- animParams:过渡动画参数;
tweenColor(node, property, startColor, endColor, animParams) {
animParams = animParams || {};
if (!animParams.frames && !animParams.duration)
animParams.duration = 5000;
if (!animParams.easing)
animParams.easing = t => t; startColor = ht.Default.toColorData(startColor);
endColor = ht.Default.toColorData(endColor); const dx = endColor[0] - startColor[0];
const dy = endColor[1] - startColor[1];
const dz = endColor[2] - startColor[2];
const da = endColor[3] - startColor[3];
const postAction = animParams.postAction;
animParams.action = (v, t) => {
const x = startColor[0] + v * dx;
const y = startColor[1] + v * dy;
const z = startColor[2] + v * dz;
const a = (startColor[3] + v * da) / 255; node.s(property, ('rgba(' + ([x, y, z, a]).join(', ')) + ')'); if (postAction) postAction(('rgba(' + ([x, y, z, a]).join(', ')) + ')');
}
return ht.Default.startAnim(animParams);
}

// 面板显示
showPanel(data) {
ht.Default.startAnim({
duration: 1000,
easing: t => t,
action: (v,t) => {
data.setScaleX(data.getScaleX() + (1 - data.getScaleX()) * v);
}
});
} // 面板隐藏
hidePanel(data) {
ht.Default.startAnim({
duration: 1000,
easing: t => t,
action: (v,t) => {
data.setScaleX(data.getScaleX() + (0 - data.getScaleX()) * v);
}
});
}

elevatorAnimation(data) {
const g3d = this.g3d;
const tag = data.getTag();
const e = data.getElevation();
const label = data.getChildAt(0);
// 判断现在所处楼层
let now = Math.ceil(e / 50);
// 下一层楼层取1~7随机数
let next = randomNumber(1, 7);
// 根据现在的楼层和下一个楼层,判断电梯运行的范围
let range = numBetween(now, next);
this.animationElevatorMap[tag] = ht.Default.startAnim({
duration: range * 800,
easing: t => t,
action: (v, t) => {
// 电梯运行位置设定
data.setElevation(now < next ? (e + (range * 50) * v) : (e - (range * 50) * v));
// 设置电梯楼层面板显示并根据电梯位置设定
if (!label) return;
const floor = Math.ceil(data.getElevation() / 50);
if (floor === label.a('text')) return;
label.a('text', floor);
// 手动刷新电梯面板信息
g3d.invalidateShape3dCachedImage(label);
},
finishFunc: () => {
// 销毁电梯间隔动画
delete this.timeoutElevatorMap[tag]; // 执行电梯间隔动画后回调电梯运行动画
this.timeoutElevatorMap[tag] = setTimeout(() => {
this.elevatorAnimation1(data);
}, Math.floor(Math.random() * 5000) + 2000);
}
});
}

park(car, key = 'Path', finishFunc) {
const dm = car.dm();
const tag = car.getTag();
const forwardPath = dm.getDataByTag(tag + '_forward' + key);
const backwardPath = dm.getDataByTag(tag + '_backward' + key);
this.animationMap[tag] = move(car, forwardPath, 'forward', undefined, 24, {
pathEndFunc: () => {
this.animationMap[tag].stop(); this.animationMap[tag] = move(car, backwardPath, 'backward', undefined, undefined, {
pathEndFunc: () => {
this.animationMap[tag].stop();
delete this.animationMap[tag]; if (finishFunc) finishFunc();
return true;
}
});
return true;
}
});
}
move 是节点沿着路径平滑移动的封装函数,主要参数为:
- node:动画节点;
- path:运行路径;
- direction:节点朝向 forward | backward;
- animParams:动画参数;
通过绘制一条运行路线的管道,ht.Default.getLineCacheInfo() 得到这条管道的点位和分割信息 cache,然后管道信息通过 ht.Default.getLineLength() 得到管道的长度,并且通过 ht.Default.getLineOffset() 来获取连线或者管道指定比例的偏移信息,从而达到移动的效果,注意的是,这里还设定了 direction 来规定动画节点的朝向,主要是为了通过 node.lookAtX() 来获取节点下一个面对的朝向的位置信息,并设置节点此时的位置,从而达到节点沿着路径平滑移动的效果。
move(node, path, direction, step = 6, interval = 75, animParams) {
let cache = path.__cache__;
if (!cache)
cache = path.__cache__ = ht.Default.getLineCacheInfo(path.getPoints(), path.getSegments()); const len = ht.Default.getLineLength(cache); animParams = animParams || {}; const face = direction === 'forward' ? 'front' : direction === 'backward' ? 'back' : direction;
let currentLen = 0;
const pathEndFunc = animParams.pathEndFunc;
const action = animParams.action;
animParams.action = (v, t) => {
if (currentLen >= len) {
// 档 pathEndFunc 返回 true 是,认为是要结束动画, 不执行后面档 action
if (pathEndFunc && pathEndFunc())
return;
}
currentLen = currentLen % len; const offset = ht.Default.getLineOffset(cache, currentLen);
const point = offset.point; node.lookAtX([point.x, node.getElevation(), point.z], face);
node.p3(point.x, node.getElevation(), point.z); currentLen = currentLen + step; if (action) action();
};
return loop(animParams.action, interval);
}
与此同时,我们还可以看到车辆行驶到车位或者离开时,车位上方的红绿灯则表示着这个车位的停放信息,是根据车辆的情况实时设定车位的状况,通过改变其信号灯 image 的 json 图标并手动刷新缓存来实现的。而缓存机制对于整体场景的流畅度是至关重要的,对于一些不必要实时刷新的面板信息,我们可以采取缓存的方式,并且在下一次更新的时候调用 Graph3dView.invalidateShape3dCachedImage(node)来手动刷新这个节点,从而大大提高了场景的性能,有关 3D 面板的属性可以参考 <HT 的 3D 手册 billboard 公告板>。
updateLight(view, light, color) {
light.s('shape3d.image', 'symbols/parking/' + color + 'Light.json');
view.invalidateShape3dCachedImage(light);
}

基于 HTML5 WebGL 的楼宇智能化集成系统(三)的更多相关文章
- 基于 HTML5 WebGL 的楼宇智能化集成系统(一)
前言 随着现代通信技术.计算机技术.控制技术的飞速发展,智能建筑已经成为现代建筑发展的主流.智能建筑是以建筑物为平台,兼备信息设施系统.信息化应用系统.建筑设备管理系统.公共安全系统等.集 ...
- 基于 HTML5 WebGL 的楼宇智能化集成系统(二)
前言 一套完整的可视化操作交互上,必不可少 2D/3D 的融合,在上期我们介绍了有关 3D 场景的环视漫游.巡视漫游以及动画效果,还包括了冷站场景.热站场景以及智慧末端的实现原理,本期主要 ...
- 基于 HTML5 + WebGL 实现 3D 挖掘机系统
前言 在工业互联网以及物联网的影响下,人们对于机械的管理,机械的可视化,机械的操作可视化提出了更高的要求.如何在一个系统中完整的显示机械的运行情况,机械的运行轨迹,或者机械的机械动作显得尤为的重要,因 ...
- 基于 HTML5 WebGL 的 CPU 监控系统
前言 科技改变生活,科技的发展带来了生活方式的巨大改变.随着通信技术的不断演进,5G 技术应运而生,随时随地万物互联的时代已经来临.5G 技术不仅带来了更快的连接速度和前所未有的用户体验,也为制造业, ...
- 基于 HTML5 + WebGL 的 3D 太阳系系统
前言 近年来随着引力波的发现.黑洞照片的拍摄.火星上存在水的证据发现等科学上的突破,以及文学影视作品中诸如<三体>.<流浪地球>.<星际穿越>等的传播普及,宇宙空间 ...
- 基于 HTML5 WebGL 的医疗物流系统
前言 物联网( IoT ),简单的理解就是物体之间通过互联网进行链接.世界上的万事万物,都可以通过数据的改变进行智能化管理.ioT 的兴起在医疗行业中具有拯救生命的潜在作用.不断的收集用户信息并且实时 ...
- 基于 HTML5 + WebGL 实现的垃圾分类系统
前言 垃圾分类,一般是指按一定规定或标准将垃圾分类储存.分类投放和分类搬运,从而转变成公共资源的一系列活动的总称.分类的目的是提高垃圾的资源价值和经济价值,力争物尽其用.垃圾在分类储存阶段属于公众的私 ...
- 基于 HTML5 WebGL 的地铁站 3D 可视化系统
前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...
- 基于 HTML5 + WebGL 实现 3D 可视化地铁系统
前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...
随机推荐
- Linux学习第六天
学习Linux环境下的挂载命令. 什么是挂载命令? 1.Windows下,mount挂载,就是给磁盘分区提供一个盘符(C,D,E,...).比如插入U盘后系统自动分配给了它I:盘符其实就是挂载,退优盘 ...
- MyBatis框架——多表查询
MyBatis多表查询, 从表中映射主表,使用 association 标签,通过设置 javaType 属性关联实体类: 主表映射从表,使用 collection 标签,通过 ofType 属性关联 ...
- HTTP2.0学习 与 Nginx和Tomcat配置HTTP2.0
目录 一.HTTP2.0 1.1 简介 1.2 新的特性 1.3 h2c 的支持度 二.Nginx 对 http2.0 的支持 2.1 Nginx 作为服务端使用http2.0 2.2 Nginx 作 ...
- [SQL]3.26--175+176+177+178+180+181+182
175.组合两个表 题目 Code SELECT FirstName, LastName, City, State FROM Person LEFT JOIN Address --由于需要Person ...
- POJ1144 tarjan+网络中割点与割边的数量
题目链接:http://poj.org/problem?id=1144 割点与割边的数量我们可以通过tarjan的思想从一个点开始对其余点进行访问.访问的顺序构成一棵dfs树,其中根节点到任何一个结点 ...
- hdu1541树状数组(降维打击)
题目链接:http://icpc.njust.edu.cn/Problem/Hdu/1541/ 题意是:在二维图上有一系列坐标,其中坐标给出的顺序是:按照y升序排序,如果y值相同则按照x升序排序.这个 ...
- 【i春秋 综合渗透训练】渗透测试笔记
网站是齐博CMS V7.0 1.要求获得管理员密码: 利用齐博CMS V7.0 SQL爆破注入漏洞即可得到管理员用户名密码 https://www.cnblogs.com/vspid ...
- In Triangle Test / To Left Test
2020-01-09 14:51:29 如何高效的判断一个点是否是包含在一个三角形的内部是计算几何里的一个基础问题. In Triangle Test问题也可以用来解决计算几何里的一个基础问题就是 凸 ...
- GitHub也会断供:美国制裁地区帐号都受限,毫无预警,个人页面直接404
请注意,GitHub也有断供危机. 如果你有GitHub私有库,是时候重新思考安全性,也是时候制定备份策略. 这不是杞人忧天,也不只温馨提示,而是已经发生的事实. 一位伊朗程序员,一觉醒来GitHub ...
- w3cshool -- 排列组合去重算法挑战
function permAlone(str) { if(str.length == 1) return str; var a = str.substr(0, 1), one = [a], count ...