基于 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 ...
随机推荐
- php 调用curl_init失败
当你在开发微信公众号,微信小程序的时候,往往会遇到困难 进入服务器,输入 tail -f /var/log/apache2/error.log 看看apache2的日志 就因为php 的curl扩展没 ...
- RestFul API 统一格式返回 + 全局异常处理
一.背景 在分布式.微服务盛行的今天,绝大部分项目都采用的微服务框架,前后端分离方式.前端和后端进行交互,前端按照约定请求URL路径,并传入相关参数,后端服务器接收请求,进行业务处理,返回数据给前端. ...
- 1. chromedriver的下载和配置
使用selenium时,需要用到不同浏览器的driver. 我常用chromedriver,所以先记录chromedriver的使用和配置.其他浏览器的driver配置大同小异. 一. 确定浏览器的版 ...
- WEB应用之httpd基础入门(二)
前文我们聊了下httpd的一些基础设置,聊了下httpd的配置文件格式,长连接.mpm的配置以及访问控制基于文件路径和URL管控,回顾请参考https://www.cnblogs.com/qiuhom ...
- Analysis of endogenous peptides released from osteoarthritic cartilage unravels novel pathogenic markers (解读人:李琼)
文献名:Analysis of endogenous peptides released from osteoarthritic cartilage unravels novel pathogenic ...
- [BJDCTF 2nd]fake google
[BJDCTF 2nd]fake google 进入页面: 试了几下发现输入xxx,一般会按的格式显示, P3's girlfirend is : xxxxx 然后猜测会不会执行代码,发现可以执行 & ...
- 直方图均衡算法(Histogram Equalized)
Lab1: Histogram Equalization 1. 实验环境(C++) 操作系统版本 MacOS Catalina 10.15 OpenCV4.0 (imgcodecs | core | ...
- 【面试QA】Attention
目录 Attention机制的原理 Attention机制的类别 双向注意力 Self-Attention 与 Soft-Attention 的区别 Transformer Multi-Head At ...
- 带有路径压缩和rank优化的并查集实现
public class unionfind2 implements UF { int[] parent; int[] rank; public unionfind2(int n) { parent= ...
- 北邮oj 97. 二叉排序树
97. 二叉排序树 时间限制 1000 ms 内存限制 65536 KB 题目描述 二叉排序树,也称为二叉查找树.可以是一颗空树,也可以是一颗具有如下特性的非空二叉树: 若左子树非空,则左子树上所有节 ...