当前位置: 首页 > 科技观察

基于HTML5的Heatmap3D应用

时间:2023-03-18 12:39:56 科技观察

Heatmap将众多数据点的信息汇聚成直观的视觉色彩效果。Heatmap已经广泛应用于天气预报、医学影像、机房温度监测等行业,甚至竞技体育领域的数据分析。已经有很多文章分享Heatmap热力图的生成原理。可以参考《How to make heat maps》和《How to make heat maps in Flex》。本文将介绍基于HTML5技术的实现,主要基于Cavans和WebGL两种HTML52D和3D技术的应用。上面最后一个例子实现的界面效果和操作视频:heatmapjs是一个知名的实现Heatmap的开源js库。这个框架已经开发了2年多。作者PatrickWied最近决定在维护开源的基础上提供付费商业支持服务。这是一件好事。这个星球上的绝大多数开源项目作者在创建了一个勉强可用的初级版本后多年都没有看到更新。但是,真正可以在线使用的产品,不需要持续改进、增强扩展性、特殊定制。服务,考虑到作者在过去两年里免费投入了这么多(在过去的2年里,我投入了500多个小时的工作来改进heatmap.js,让它成为一个真正伟大的库。),我希望这个文章也可以帮助作者在国内做起点宣传。Heatmapjs采用Canvas二维绘制方式。这种基于CPU的绘制方式,几十万个点还好,但是如果需要实时计算几千个节点的效果,还是要依赖并发能力更强大的GPU方式,如果采用HTML5,只能是WebGL方案。幸运的是,FlorianBoesch在他的♂博客中提供了一种基于WebGL的heatmap方法,并在https://github.com/pyalot/webgl-heatmap上开源。两个开源库质量都不错,一个是基于Canvas的,一个是基于WebGL的。后者性能更高,但需要支持WebGL的浏览器。heatmapjs的文档示例比较全面,但是两者的接口都非常简单易学。代码只有几百行,您可以根据项目情况选择甚至进行代码修改和优化。回到我们要实现的例子,我会使用heatmapjs在内存中实时计算热图,结合hightopo的HTforWeb3Dengine,一堆节点相连的3D网络拓扑图,其中节点代表热度sources,离地面越近,地温越高,所以将每个节点的xz平面坐标信息作为点的xy二维坐标信息传递给heatmapjs,三维的高程node为y轴信息,作为距地面的距离信息,距离越大,传给heatmapjs的值越小,最后启动HTforWeb的3D拓扑自动布局弹性算法,所以可以直观的观察当图元节点动态变化时地板温度在不同空间位置的Heatmap变化效果。代码的核心是重载forceLayout.onRelaxed函数。在每次自动布局过程中,将所有热源节点的信息构造成热图所需的数据,同时通过ht.Default.setImage('hm-bottom',heatmap._renderer.canvas);注册将热力图的画布作为HT图像,并将注册的'hm-bottom'图像绑定到floorprimitive,这样就可以在内存中绘制画布,然后通过3D引擎将Cavnas用作纹理HTforWeb动态呈现信息到3D场景的效果。整个实现代码不到一百行如下。也可以使用https://github.com/pyalot/webgl-heatmap的WebGL方式来实现。这是一个从3D到2D再到3D的有趣过程。这就是HTML5技术在没有Seam的情况下能够融合各种方案的魅力!最大值=500;宽度=1024;身高=512;functioninit(){dataModel=newht.DataModel();g3d=newht.graph3d.Graph3dView(dataModel);g3d.getMoveMode=function(e){return'xyz';};view=g3d.getView();view.className='主要';document.body.appendChild(视图);window.addEventListener('resize',function(e){g3d.invalidate();},false);heatmap=h337.create({width:WIDTH,height:HEIGHT});ht.Default.setImage('hm-bottom',heatmap._renderer.canvas);varfloor=newht.Node();floor.s3(宽度,1,高度);floor.s({'3d.selectable':false,'layoutable':false,'all.visible':false,'top.visible':true,'top.image':'hm-bottom','top.reverse.flip':true,'bottom.visible':true,'bottom.transparent':true,'bottom.opacity':0.5,'bottom.reverse.flip':true});数据模型。添加(楼层);varroot=创建节点();for(vari=0;i<3;i++){variNode=createNode();createEdge(根,iNode);对于(varj=0;j<3;j++){varjNode=createNode();createEdge(iNode,jNode);}}forceLayout=newht.layout.Force3dLayout(g3d);forceLayout.start();forceLayout.onRelaxed=function(){varpoints=[];dataModel.each(function(data){if(datainstanceofht.Node&&data!==floor){varp3=data.p3();if(p3[1]>MAX){p3[1]=MAX;data.setElevation(MAX);}elseif(p3[1]<-MAX){p3[1]=-MAX;data.setElevation(-MAX);}points.push({x:p3[0]+WIDTH/2,y:p3[2]+HEIGHT/2,值:MAX-Math.abs(p3[1])});}});heatmap.setData({data:points,min:0,max:MAX});};}functioncreateNode(){varnode=newht.Node();node.s({'shape3d':'sphere','shape3d.color':'#E74C3C','shape3d.opacity':0.8,'shape3d.transparent':true,'shape3d.reverse.cull':true});node.s3(20,20,20);dataModel.add(节点);返回节点;}functioncreateEdge(sourceNode,targetNode){varedge=newht.Edge(sourceNode,targetNode);edge.s({'edge.width':3,'edge.offset':10,'shape3d':'cylinder','shape3d.opacity':0.7,'shape3d.transparent':true,'shape3d.reverse.cull':true});dataModel.add(边缘);返回;}本文来自:http://my.oschina.net/xhload3d/blog/312648