前言在当今的制造业中,基于数据制定和管理生产策略已经成为一种趋势,尤其是在工业4.0的浪潮下,数据策略成为了很多制造业的优先策略公司。数据可视化有助于更直观地指导决策,成为数据分析传达信息的重要工具。通过数据可视化系统帮助实现数据驱动的工业世界,为工业4.0提供更灵活、敏捷、高效、个性化的数据支持。今天给大家带来一个使用Hightopo的HTforWeb产品实现的水泥厂可视化系统。系统预览本案例共有七个子系统:数据总览——以年、月、时间为单位显示全厂各项数据窑系统运行概况——用窑过程动画展示窑的实时运行状态system系统操作--用动画流程图展示整个系统的运行生料质量控制--用图表和流程图展示各种原料的配比熟料质量控制--用动画流程图展示各种熟料的配比使用图表流程图监控煤粉质量智能物流——通过3D场景实时监控进出车辆,切换各原料运输子系统页面切换不同子系统时,左侧菜单和顶部标题不需要切换的,所以我们把需要切换的内容部分放在不同的Block中。Block类型本身不绘制任何内容。作为其他节点的父节点,可以与子节点的大小同步。当它隐藏或显示时,所有子节点将相应地隐藏或显示。所以我们在切换子系统的时候,只需要控制对应Block的显示和隐藏即可,而不需要加载和切换多个绘图。流量图在数据概览页面,流量图展示了每年各地区的水泥销量。这里我们使用Shape类型绘制线段来连接source和sink,并使用流动效果来表示销售关系。流水效果可以通过简单引入HT的ht-flow.js插件来实现,代码如下://获取线段的父节点this.flowParent=dm.getDataByTag('saleFlowParent');//遍历得到所有段this.flowParent.eachChild(child=>{//开启流,设置流样式child.s({//开启流'flow':true,//设置大小ofthelargestelementintheflowgroup'flow.element.max':4,//设置流组中元素渐变阴影的中心色'flow.element.shadow.begincolor':'#49e5fe',//设置流组'flow.element.shadow.max'中最大元素的渐变阴影大小:16,//设置流组'flow.element.shadow'中元素的渐变阴影边缘颜色。endcolor':'rgba(73,229,254,0)',});});窑系统动画在窑系统运行页面,窑工艺动画非常直观地展示了窑系统的实时运行状态。画面中传送带上输送的火焰、水和熟料的动画效果,为了在性能较差的设备上流畅运行,我通过切换不同的矢量图形来实现。这里使用了HT向量中的状态机制。首先绘制多个不同的向量分量。每个组件都可以定义一个state来决定它显示在哪个状态,可以通过data.s('state')修改节点state来实现,效果如下:使用定时器不断改变状态值节点。相关代码如下:this._stateTimer=setInterval(()=>{stateNodes.forEach(node=>{this.stateAnimation(node);});},180);//切换状态stateAnimation(node){letstateIndex=(node.a('stateIndex')||0)%stateEnum.length,state=stateEnum[stateIndex].value;node.s('状态',状态);node.a('stateIndex',++stateIndex);}流程图动画流程图中的流线也是使用ht-flow.js插件实现的。由于图上的线段比较多,我把不同的线段分在不同的Block下,遍历它的子节点来设置样式。代码如下://设置流属性setNodeFlow(data,value){if(datainstanceofht.Block){data.eachChild(child=>{this.setNodeFlow(child,value);});}elseif(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(datainstanceofht.Block){data.eachChild(child=>{this.setNodeDashFlow(child,value);});}elseif(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(datainstanceofht.Block){data.eachChild(child=>{this.setNodeOpacity(孩子,价值);});}else{data.s('opacity',value);}}接下来只需要一个一个执行动画://启动流程图动画start(){let{eo,eoInput,eoLine1,eoKind,eoCalu}=this;//工况输入透明动画this.gv.enableFlow(30);this.setNodeOpacity(eo);this.setNodeFlow(eo,false);(newPromise((resolve,reject)=>{this.animtion=startAnim({frames:16,interval:5,finishFunc:()=>{resolve()},action:(v,t)=>{this.setNodeOpacity(eoInput,0.5+0.5*v);}});})).then(()=>{//连接透明动画,流返回newPromise((resolve,reject)=>{this.animtion=startAnim({frames:12,interval:10,finishFunc:()=>{this.setNodeFlow(eoLine1,true);this.timer=setTimeout(()=>{resolve()},1500);},动作:(v,t)=>{this.setNodeOpacity(eoLine1,0.5+0.5*v);}});})}).then(()=>{//软计算透明动画returnnewPromise(resolve=>{this.animtion=startAnim({frames:16,interval:5,finishFunc:()=>{resolve()},动作:(v,t)=>{this.setNodeOpacity(eoKind,0.5+0.5*v);this.setNodeOpacity(eoCalu,0.5+0.5*v);}});});}).then(()=>{//软计算透明点流returnnewPromise(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拓扑图上实现,嵌入任意第三方HTMLDOM元素。不过这里要注意,HT的绘图是通过Canvas实现的,renderHTML的DOM元素必须在Canvas之上。使用renderHTML的DOM和常规Canvas上绘制的图元是不可能有层次控制的可能的。renderHTML函数属性中的代码如下所示:renderHTML:function(data,gv,cache){//避免重复创建g3dif(!cache.g3d){//创建一个3D视图组件varg3d=cache.g3d=newht.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的值varsceneURL=data.a('sceneURL');//获取原语的自定义属性onPostDeserialize的值varonPostDeserialize=data.a('onPostDeserialize');//当原始自定义属性sceneURL发生变化时,清除旧的dataModel并反序列化新的sceneURLif(cache.g3d.sceneURL!==sceneURL){cache.g3d.dm().clear();cache.g3d.sceneURL=sceneURL;if(sceneURL){cache.g3d.deserialize(sceneURL,function(json,dm,g3d,datas){//反序列化后的回调函数在number中执行onPostDeserialize函数onPostDeserialize&&onPostDeserialize(json,dm,g3d,datas);});}}returncache.g3d;}嵌入3D场景后,下一步就是根据后台进入的车辆实现水泥厂的车辆动画,根据工厂数据,我们创建承载不同原始数据的车辆模型物料,让它们沿着不同的路径到达相应的工厂。同样使用Shape类型预先绘制路径,根据Shape的Points和Segments信息实现车辆沿路径行驶的动画。相关代码如下:carAnimation(car,path,duration){//车辆行驶动画ht.Default.startAnim({duration:duration,easing:E??asing.easeNone,action:function(v,t){//设置theoffsetletoffset=Math.floor(v*100);//根据偏移量获取路径上的点坐标letposition=ht.Default.getPercentPositionOnPoints(path.getPoints(),path.getSegments(),offset);//根据偏移量,得到路径上的点和路径的切线角度letangle=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
