关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

云南大王-基于 HTML5 WebGL 的 水泥工厂可视化系统

发布时间:2020-04-16 00:00:00
前言     如今的制造行业,基于数据进行生产策略制定与管理已经成为一种趋势,特别是 工业4.0 的浪潮下,数据战略已经成为很多制造企业的优先战略,而数据可视化以更直观的方式,帮助指导决策,成为数据分析传递信息的重要工具。通过数据可视化系统助力实现数据驱动的工业世界,为 工业4.0 提供更加灵活、敏捷、高效、个性化的数据支撑。今天就给大家带来一个采用 Hightopo 的 HT for Web 产品实现了一个水泥工厂可视化系统。 系统预览     本案例共有七个子系统: 数据概况 -- 展示全厂年月时间单位的各项数据概况 窑系统运行 -- 用窑工艺流程动画展示窑系统实时运行状态 系统运行情况 -- 用动画流程图展示整个系统运行情况 生料质量控制 -- 用图表和流程图展示各种生料的配比情况 熟料质量控制 -- 用动画流程图展示各种熟料的配比情况 煤粉质量控制 -- 用图表和流程图对煤粉质量进行监控 智能物流 -- 通过 3D 场景实时监控进出厂车辆,和各项原料运输情 子系统页面切换       切换不同子系统时,左侧菜单和顶部标题是不需要切换的,所以我们把需要切换的内容部分别放在不同的 Block 中,Block 类型,本身不绘制任何内容,用于作为其它节点的父节点,可以与子节点同步大小,当它隐藏或显示时,所有子节点都会跟着隐藏或显示。所以当我们切换子系统时只需要控制对应的 Block 显示隐藏,而不需要去加载切换多张图纸。 流向地图       在数据概况页面中,流向地图展示年度水泥向各地区的销售情况,这里我们用 Shape 类型绘制线段来连接源地和汇地,用流动效果表示销售关系。流动效果只需引入 HT 的 ht-flow.js 插件,即可通过简单的属性设置实现,代码如下: // 获取线段的父节点 this.flowParent = dm.getDataByTag('saleFlowParent'); // 遍历得到所有线段 this.flowParent.eachChild(child => { // 开启流动,设置流动样式 child.s({ // 开启流动 'flow': true, // 设置流动组中最大元素的尺寸 'flow.element.max': 4, // 设置流动组中的元素的渐变阴影中心颜色 'flow.element.shadow.begincolor': '#49e5fe', // 设置流动组中的最大元素的渐变阴影尺寸 'flow.element.shadow.max': 16, // 设置流动组中的元素的渐变阴影边缘颜色 'flow.element.shadow.endcolor': 'rgba(73, 229, 254, 0)', }); });  窑系统动画     在窑系统运行页面中,窑工艺流程动画很直观的展示了窑系统实时运行状态。画面中火焰、水和熟料在传送带上运输的动画效果,为了在性能较差的设备上也能流畅运行,我通过切换不同矢量图形的方式实现。这里用到了 HT 矢量中状态机制,先绘制多个不同的矢量组件,每个组件都可以定义状态来决定自己在哪个状态下显示,只要通过 data.s('state') 修改节点状态就可以实现如下效果:     使用一个定时器,不断地改变节点的状态值,相关代码如下: this._stateTimer = setInterval(() => { stateNodes.forEach(node => { this.stateAnimation(node); }); }, 180); //切换状态 stateAnimation(node) { let stateIndex = (node.a('stateIndex') || 0) % stateEnum.length, state = stateEnum[stateIndex].value; node.s('state', state); node.a('stateIndex', ++stateIndex); }   流程图动画     流程图中流动线同样是使用 ht-flow.js 插件实现。由于图纸上的线段比较多,我把不同的线段分组放在不同的 Block 下,遍历其子节点设置样式,代码如下: //设置流动属性 setNodeFlow (data, value) { if (data instanceof ht.Block) { data.eachChild(child => { this.setNodeFlow(child, value); }); } else if (data.getDisplayName() === 'line'){ data.s({ 'flow': value, 'flow.element.max': 4, 'flow.element.count': 1, 'flow.count': 5, 'flow.step': 10 }); } } //设置虚线流动属性 setNodeDashFlow(data, value) { if (data instanceof ht.Block) { data.eachChild(child => { this.setNodeDashFlow(child, value); }); } else if (data.getDisplayName() === 'border'){ if (value) { data.s({ 'shape.dash.flow': true, 'shape.dash': true }); } else { data.s({ 'shape.dash.flow': false, 'shape.dash': false }); } } }     为了使动画看起来更顺畅,我给一些节点加上透明度动画,设置节点透明度的代码如下: //设置节点透明度 setNodeOpacity (data, value = 0.5) { if (data instanceof ht.Block) { data.eachChild(child => { this.setNodeOpacity(child, value); }); } else { data.s('opacity', value); } }     接下来只需要依次执行动画: //开始流程图动画 start() { let {eo, eoInput, eoLine1, eoKind, eoCalu} = this; //工况输入透明度动画 this.gv.enableFlow(30); this.setNodeOpacity(eo); this.setNodeFlow(eo, false); (new Promise((resolve, reject) => { this.animtion = startAnim({ frames: 16, interval: 5, finishFunc: () => {resolve()}, action: (v, t) => { this.setNodeOpacity(eoInput, 0.5 + 0.5 * v); } }); })).then(() => { //连线连线透明动画,流动 return new Promise((resolve, reject) => { this.animtion = startAnim({ frames: 12, interval: 10, finishFunc: () => { this.setNodeFlow(eoLine1, true); this.timer = setTimeout(() => {resolve()}, 1500); }, action: (v, t) => { this.setNodeOpacity(eoLine1, 0.5 + 0.5 * v); } }); }) }).then(() => { //软计算透明动画 return new Promise(resolve => { this.animtion = startAnim({ frames: 16, interval: 5, finishFunc: () => {resolve()}, action: (v, t) => { this.setNodeOpacity(eoKind, 0.5 + 0.5 * v); this.setNodeOpacity(eoCalu, 0.5 + 0.5 * v); } }); }); }).then(() => { //软计算透明虚线流动 return new Promise(resolve => { this.setNodeDashFlow(eoKind, true); this.setNodeDashFlow(eoCalu, true); this.timer = setTimeout(() => { this.setNodeDashFlow(eoKind, false); this.setNodeDashFlow(eoCalu, false); resolve(); }, 3000); }); }).then(() => { ...... }) }   智能物流     前面六个子系统均为 2D 界面,而智能物流页面则是嵌入了一个 3D 场景。实现方式是通过定义 HT 矢量 JSON 的 renderHTML 函数属性,可实现在 GraphView 拓扑图上,嵌入任意第三方 HTML DOM 元素。不过这里也要注意一点,HT 的图纸是 Canvas 实现的,renderHTML 的 DOM 元素一定在 Canvas 之上,使用 renderHTML 的 DOM 与常规 Canvas 上绘制的图元不可能有层级控制可能性。下面展示一下 renderHTML 函数属性里的代码: renderHTML : function (data, gv, cache) { // 避免重复创建g3d if (!cache.g3d) { // 创建 3D 视图组件 var g3d = cache.g3d = new ht.graph3d.Graph3dView(); // 布局函数,根据图元的位置信息摆放HTML元素 g3d.layoutHTML = function () { gv.layoutHTML(data, g3d, true); }; // 阻止事件冒泡 g3d.getView().addEventListener('mousedown', function (event) { event.stopPropagation(); }); g3d.getView().addEventListener('touchstart', function (event) { event.stopPropagation(); }); } // 获取图元自定义属性sceneURL的值 var sceneURL = data.a('sceneURL'); // 获取图元自定义属性onPostDeserialize的值 var onPostDeserialize = data.a('onPostDeserialize'); // 当图元自定义属性sceneURL改变时,清除旧dataModel,反序列化新的sceneURL if (cache.g3d.sceneURL !== sceneURL) { cache.g3d.dm().clear(); cache.g3d.sceneURL = sceneURL; if (sceneURL) { cache.g3d.deserialize(sceneURL, function (json, dm, g3d, datas) { // 在反序列化后的回调函数中,执行onPostDeserialize函数 onPostDeserialize && onPostDeserialize(json, dm, g3d, datas); }); } } return cache.g3d; }      3D场景嵌入后,接下来实现水泥厂内的车辆动画。根据后台传来车辆进入工厂的数据,我们创建运载不同原料的车辆模型,让它们沿着不同的路径抵达对应的厂房。同样是用 Shape 类型事先绘制好路径,根据 Shape 的 Points 和 Segments 信息,实现车辆沿着路径行驶动画。相关代码如下: carAnimation(car, path, duration) { // 车辆行驶动画 ht.Default.startAnim({ duration: duration, easing: Easing.easeNone, action: function (v, t) { // 设置偏移量 let offset = Math.floor(v * 100); // 根据偏移量得到在路径上的点坐标 let position = ht.Default.getPercentPositionOnPoints(path.getPoints(), path.getSegments(), offset); // 根据偏移量得到在路径上的点于路径切线角度 let angle = ht.Default.getPercentAngle(path.getPoints(), path.getSegments(), offset); // 设置车辆位置坐标及旋转角度 car.setX(position.x); car.setY(position.y); car.setRotationY(Math.PI / 2 - angle); }, }); } 总结     工业互联网是工业发展的必经之路,我们国家是一个工业大国,正处在工业转型升级的关键时刻,面临着人工成本上升、原材料价格波动、贸易竞争日益加剧等问题,迫切需要提高效率、降低生产成本。只有坚定不移地推动工业互联网落地,加快更多企业的数字化转型和智能化改造,才有能让在全球化竞争中立于不败之地。可视化作为智能化数字化的最后一环,让复杂抽象的数据变得真正可知可感,帮助决策者发现规律,洞悉未来,为企业提速增效。     还有更多的可视化案例可以参考:https://www.hightopo.com/demos/index.html

相关阅读

centos7系统中忘记了root管理员账号密码的解决方式公司管理必须的20条军规[参考]云南昆明天猫旗舰店如何开_怎么开_要什么条件云南大王-通俗理解spring源码(三)—— 获取xml的验证模式 云南大王-用户登录 云南大王-【Golang进阶】指针的详细讲解 云南大王-Java 单线程代码ThreadLocal串值问题 云南大王-Java 实例级别的锁和类级别的锁 云南大王-工作流引擎会签,加签,主持人,组长模式专题讲解 云南大王-Android连载5云南大王-NTP对时器(NTP对时服务器)重要性!京准电子科技 云南大王-关于redis单线程的分析 云南大王-CVE云南大王-PHP SESSION反序列化本地样例分析 云南大王-这不就是多线程ThreadPoolExecutor和阻塞队列吗 云南大王-Tomcat AJP 文件包含漏洞(CVE云南大王-讲真,这两款idea插件,能治愈你英语不好的病 云南大王-消息中间件ActiveMQ、RabbitMQ、RocketMQ、ZeroMQ、Kafka如何选型? 云南大王-JVM系列十三(类加载器). 云南大王-Win10安装MySQL8压缩包版 云南大王-初始WebApi(2) 云南大王-初识人工智能(二):机器学习(一):sklearn特征抽取 云南大王-Popup中ListBox的SelectChange事件关闭弹出窗体后主窗体点击无效BUG 云南大王-基础知识记录 云南大王-FastDFS搭建图片服务器 云南大王-git/sourcetree解决本地仓库历史合并到线上仓的历史数据合并问题_refusing to merge unrelated histories 云南大王-js判断字符是否在数组中【转】 云南大王-Python 云南大王-面向对象之多线程(可捎带电梯调度) 云南大王-Python练习题2.5求奇数分之一序列前N项和(存在问题) 云南大王-React 中的前端路由 react云南大王-VSCODE 远程开发树莓派 云南大王-React新闻网站云南大王-vs .net CS0006 C# 未能找到元数据文件 .dll 云南大王-Vue.js 技术揭秘 云南大王-流程控制语句云南大王-Python学习笔记:Python的时间操作(time,datetime,timedelta,calendar) 云南大王-流程控制语句云南大王-golang Gin framework with websocket 云南大王-多重判断if..else嵌套语句 云南大王-用户登录 云南大王-流程控制语句云南大王-密码类 云南大王-Unity2018发布WebGL注意事项总结 云南大王-web系统安全运营之基础云南大王- 流程控制语句云南大王-中型WPF客户端开发项目总结(3.3.4) 云南大王-流程控制语句云南大王-流程控制语句云南大王-流程控制语句云南大王-中型WPF客户端开发项目总结(4) 云南大王-流程控制语句云南大王-ASP.NET Core笔记(4) 云南大王-C# 基础知识系列云南大王-让 .NET 轻松构建中间件模式代码(二) 云南大王-基于 HTML5 WebGL 的 水泥工厂可视化系统 云南大王-.NET Core 3 WPF MVVM框架 Prism系列之导航系统 云南大王-《JavaScript异步编程》精读笔记 云南大王-合理使用CSS框架,加速UI设计进程 云南大王-CLSID 为 {000209FF云南大王-从零基础转行到前端大牛,需要经过哪几个阶段? 云南大王-一个简单的例子看明白 async await Task 云南大王-【目前】宇宙第一IDE Visual Studio 合并压缩css、js扩展组件云南大王-写一个通用的List集合导出excel的通用方法 云南大王-Bootstrap4 按钮组+徽章(Badges)+进度条+分页+列表组 云南大王-Web前端工程师需要学些什么? 云南大王-react嵌套路由 云南大王-【java框架】Struts2(2) 云南大王-javaSE笔记云南大王-.net core 集成 sentry 进行异常报警 云南大王-Java の 四种引用 云南大王-JVM 虚拟机&&类加载(一) 云南大王-使用Fastjson实现JSON与JavaBean之间互相转换 云南大王-Python操作Oracle数据库:cx_Oracle 云南大王-为什么要用内插字符串代替string.format 云南大王-作为字节跳动的面试官,有些话我不得不说! 云南大王-微信公众号自定义菜单与启用服务器配置冲突(图文消息、链接及文本回复) 云南大王-C#队列学习笔记:RabbitMQ延迟队列 云南大王-Disruptor 基础篇 云南大王-C#获取设备(Audio和Video)名称 简单整理 云南大王-基于注解的IOC配置 云南大王-C#调用EnumDevice获取设备信息 云南大王-Jenkins基础系统之更换镜像源 云南大王-Jenkins基础系统之完整的.net项目编译 云南大王-Scala学习系列(二)——环境安装配置 云南大王-WinForm中DataGridView复制选中单元格内容解决方案 云南大王-关键词匹配优化(第0篇)—— 问题和思路 云南大王-ASP.NET CORE WEBAPI文件下载 云南大王-GC垃圾回收器 云南大王-多线程之旅(Task 任务) 云南大王-当模板方法遇到了委托函数,你的代码又可以精简了 云南大王-基于.NetCore3.1搭建项目系列 —— 使用Swagger导出文档 (补充篇) 云南大王-关键词匹配优化(第1篇)—— 测试计算过程 云南大王-原理解密 → Spring AOP 实现动态数据源(读写分离),底层原理是什么 云南大王-Navicat 密码加密算法 云南大王-【WPF学习】第六十六章 支持可视化状态 云南大王-composer安装 windows 云南大王-ASP.NET Core中的Controller 云南大王-HttpClient来自官方的JSON扩展方法 云南大王-Python3标准库:http.cookies HTTP cookie
/template/Home/Zkeys/PC/Static