基于HTML5实现的Heatmap热图3D应用

简介: Heatmap热图通过众多数据点信息,汇聚成直观可视化颜色效果,热图已广泛被应用于气象预报、医疗成像、机房温度监控等行业,甚至应用于竞技体育领域的数据分析。 已有众多文章分享了生成Heatmap热图原理,可参考《How to make heat maps》和《How to make heat ...

Heatmap热图通过众多数据点信息,汇聚成直观可视化颜色效果,热图已广泛被应用于气象预报、医疗成像、机房温度监控等行业,甚至应用于竞技体育领域的数据分析。

Viz Libero heat map

已有众多文章分享了生成Heatmap热图原理,可参考《How to make heat maps》和《How to make heat maps in Flex》,本文将介绍基于HTML5技术的实现方式,主要基于Cavans和WebGL这两种HTML5的2D和3D技术的应用,先上最终例子实现的界面效果和操作视频

IMG_1036


实现Heatmap的开源js库比较出名的就是  heatmapjs ,该框架发展了2年多,作者Patrick Wied最近决定在保持开源的基础上,提供有偿的商业支持服务,这是好事,地球上绝大部分开源项目作者搞个barely可用的初级版本后,就多年不见更新了,而真正能实际上线使用的产品哪有不需要持续完善、增强可扩展性以及提供特殊定制服务的,考虑到作者这两年已无偿投了这么多( Over the last 2 years, I devoted more than 500 hours of work to improving heatmap.js to make it a truly great library. ),希望此文也能帮作者在国内起点宣传作用。

heatmapjs 采用的Canvas的2D绘制方式实现,这种基于CPU的绘制方式对于几百几千的点还凑合,但如果需要实时运算成千上万节点效果的,还是得依靠并发性更强大的GPU方式,采用HTML5的话只能是WebGL方案,还好Florian Boesch在《High Performance JS heatmaps》博客中提供了基于WebGL实现的heatmap方式,并将其开源在https://github.com/pyalot/webgl-heatmap  上,这两个开源库质量都还不错,一个基于Canvas实现,一个基于WebGL实现,后者性能高点,但需要支持WebGL的浏览器,heatmapjs 的文档例子比较全面,但两者接口都非常简单易学,代码也都就几百行,你完全可以根据项目情况选择甚至进行代码改造优化。

回到我们要实现的例子,我将采用heatmapjs在内存中实时运算出热图,结合hightopoHT for Web的3D引擎,以一堆节点连线关系的3D的网络拓扑图,其中节点代表热源,其越接近地面则地面温度越高,这样每个节点的xz面坐标信息作为要传入给heatmapjs的点xy二维坐标信息,三维节点的elevation也就是y轴信息,则作为离地面的距离信息,距离越大转成要传入heatmapjs的value值越小,最后启动HT for Web的三维拓扑自动布局弹力算法,这样可直观的观察图元节点在不同的空间位置动态变化时地板的温度热图变化效果。

代码核心就在重载forceLayout.onRelaxed函数,在每次自动布局过程将所有热源节点的信息构建成heatmap需要的数据,同时通过ht.Default.setImage(‘hm-bottom’, heatmap._renderer.canvas);将热图的canvas注册成HT的图片,而floor的地板图元绑定了注册的’hm-bottom’图片,这样就实现了内存绘制canvas,然后通过HT for Web的3D引擎将Cavnas作为贴图信息动态呈现到3D场景的效果。

整个实现代码如下不到百行,你也可以采用https://github.com/pyalot/webgl-heatmap 的WebGL方式来实现,这样就是3D到2D再到3D的有趣过程,这就是HTML5技术可无缝融合各种方案的魅力!

 1 MAX = 500;
 2 WIDTH = 1024;
 3 HEIGHT = 512;        
 4 function init() {                           
 5     dataModel = new ht.DataModel();            
 6     g3d = new ht.graph3d.Graph3dView(dataModel);                            
 7     g3d.getMoveMode = function(e){ return 'xyz'; };                        
 8     view = g3d.getView();            
 9     view.className = 'main';
10     document.body.appendChild(view);    
11     window.addEventListener('resize', function (e) { g3d.invalidate(); }, false);            
12     heatmap = h337.create({ width: WIDTH, height: HEIGHT });                                   
13     ht.Default.setImage('hm-bottom', heatmap._renderer.canvas);            
14     var floor = new ht.Node();
15     floor.s3(WIDTH, 1, HEIGHT);
16     floor.s({
17         '3d.selectable': false,
18         'layoutable': false,
19         'all.visible': false,
20         'top.visible': true,
21         'top.image': 'hm-bottom',
22         'top.reverse.flip': true,
23         'bottom.visible': true,
24         'bottom.transparent': true,
25         'bottom.opacity': 0.5,
26         'bottom.reverse.flip': true                
27     });
28     dataModel.add(floor);            
29     var root = createNode();                   
30     for (var i = 0; i < 3; i++) {
31         var iNode = createNode();                       
32         createEdge(root, iNode);
33         for (var j = 0; j < 3; j++) {
34             var jNode = createNode();                            
35             createEdge(iNode, jNode);                                                         
36         }
37     }                   
38     forceLayout = new ht.layout.Force3dLayout(g3d);  
39     forceLayout.start();
40     forceLayout.onRelaxed = function(){
41         var points = [];
42         dataModel.each(function(data){
43             if(data instanceof ht.Node && data !== floor){
44                 var p3 = data.p3();
45                 if(p3[1] > MAX){
46                     p3[1] = MAX;
47                     data.setElevation(MAX);
48                 }
49                 else if(p3[1] < -MAX){
50                     p3[1] = -MAX;
51                     data.setElevation(-MAX);
52                 }                        
53                 points.push({
54                     x: p3[0] + WIDTH/2,
55                     y: p3[2] + HEIGHT/2,
56                     value: MAX - Math.abs(p3[1])
57                 });
58             }
59         });
60         heatmap.setData({data: points, min: 0, max: MAX});
61     };
62 }
63 function createNode(){
64     var node = new ht.Node();             
65     node.s({
66         'shape3d': 'sphere',
67         'shape3d.color': '#E74C3C',
68         'shape3d.opacity': 0.8,
69         'shape3d.transparent': true,
70         'shape3d.reverse.cull': true
71     });
72     node.s3(20, 20, 20);
73     dataModel.add(node);
74     return node;
75 }
76 function createEdge(sourceNode, targetNode){
77     var edge = new ht.Edge(sourceNode, targetNode);
78     edge.s({
79         'edge.width': 3,
80         'edge.offset': 10,                
81         'shape3d': 'cylinder',
82         'shape3d.opacity': 0.7,
83         'shape3d.transparent': true,
84         'shape3d.reverse.cull': true
85     });
86     dataModel.add(edge);
87     return edge;
88 }   

 

目录
相关文章
|
9天前
|
JavaScript 前端开发 UED
HTML 超链接的多种类型及应用
【10月更文挑战第17天】HTML 超链接类型丰富多样,它们共同构成了网页中不可或缺的导航和交互元素。通过合理地选择和运用这些超链接类型,我们可以为用户创造更加流畅和便捷的浏览体验,提升网站的可用性和吸引力。
11 1
|
1月前
|
移动开发 前端开发 JavaScript
HTML5 新的 Input可以有哪些好玩的应用
HTML5的新输入类型为应用带来了多种创新和互动功能,显著提升了用户体验和界面趣味性。例如,颜色选择器可动态改变网站主题色;滑块控制适用于音量或亮度调节;日期和时间输入便于预约系统的设计;互动式表单结合多种输入类型实现高效的数据收集;猜数字游戏增加用户参与度;实时搜索建议优化网站搜索功能;图像预览功能让用户上传图片前预览效果;密码可见性切换按钮提升表单的可用性;结合用户位置的电话号码输入则能提供附近服务信息。这些应用场景不仅使网站更具吸引力,还增强了用户的互动体验。
|
2月前
|
移动开发 JavaScript 数据管理
HTML5 拖放在游戏中的应用
HTML5的拖放功能在游戏开发中广泛应用,尤其在创建交互式网页游戏时。它支持多种场景,如拖动角色或物品、选择和装备物品、拼图或配对游戏以及自定义界面布局。通过简单的HTML和JavaScript代码,可实现流畅的拖放交互,并提供视觉反馈,增强用户体验。此外,还需考虑设备兼容性和数据管理,确保游戏在不同设备和浏览器上都能良好运行。总之,HTML5拖放功能使网页游戏更生动有趣。
|
2月前
|
移动开发 前端开发 JavaScript
HTML5 Canvas详解及应用
HTML5 Canvas 允许通过 JavaScript 在网页上动态绘制图形、动画等视觉内容。首先在 HTML 中定义 `&lt;canvas&gt;` 元素,并通过 JavaScript 获取画布上下文进行绘制。常见方法包括绘制矩形、路径、圆形和文本,以及处理图像和创建动画效果。适用于游戏开发、数据可视化、图像编辑和动态图形展示等多种应用场景。需要注意性能优化、无状态绘制及自行处理事件等问题。
|
3月前
|
前端开发
HTML+CSS动画实现动感3D卡片墙:现代Web设计的视觉盛宴
HTML+CSS动画实现动感3D卡片墙:现代Web设计的视觉盛宴
|
3月前
|
存储 移动开发 开发者
|
3月前
|
自然语言处理 前端开发 开发者
|
2月前
|
XML 前端开发 JavaScript
Html:CSS介绍
Html:CSS介绍
47 1
|
2月前
|
前端开发
Html:CSS的书写位置
Html:CSS的书写位置
27 0
|
1月前
|
前端开发 JavaScript 搜索推荐
打造个人博客网站:从零开始的HTML和CSS之旅
【9月更文挑战第32天】在这个数字化的时代,拥有一个个人博客不仅是展示自我的平台,也是技术交流的桥梁。本文将引导初学者理解并实现一个简单的个人博客网站的搭建,涵盖HTML的基础结构、CSS样式的美化技巧以及如何将两者结合来制作一个完整的网页。通过这篇文章,你将学会如何从零开始构建自己的网络空间,并在互联网世界留下你的足迹。