Heatmap 3D application based on HTML5
Heatmap heat maps converge into visual color effects through various data points. Heat maps have been widely used in meteorological forecasting, medical imaging, data center temperature monitoring, and other industries, it is even used for data analysis in the field of competitive sports.
Many articles have shared the Heatmap generation principle. For details, refer to How to make heat maps and How to make heat maps in Flex. This article introduces the implementation method based on the HTML5 technology, mainly based on the application of 2D and 3D HTML5 technologies such as Cavans and WebGL, the interface effects and operation videos implemented in the final example are as follows:
Heatmapjs is a well-known open-source js library for implementing Heatmap. This framework has been developed for more than two years. The author Patrick Wied recently decided to provide paid commercial support services based on the open-source architecture, this is a good thing. Most open-source project authors on earth haven't updated this many years after creating an available primary version of barely, which of the following products can be used online without the need to continuously improve, enhance scalability, and provide special customized services, considering that the author has invested so much in the past two years (Over the last 2 years, I was tedmore than 500 hoursof work to improving heatmap. js to make it a truly great library .), I hope this article will help the author publicize the role in China.
Heatmapjs uses the Canvas 2D rendering method. This CPU-based rendering method is applicable to hundreds of thousands of points. However, if you need to calculate the effects of thousands of nodes in real time, we still have to rely on the more powerful concurrency GPU method. If we use HTML5, we can only use the WebGL solution. Fortunately, Florian Boesch provides the WebGL-based heatmap method in the "High Performance JS heatmaps" blog, and open-source.
Back to the example we want to implement, I will use heatmapjs to calculate the heat map in the memory, combined with the hightopo HT for Web 3D engine, A 3D network topology with a heap of node connections. A node represents a heat source. The closer the node is to the ground, the higher the ground temperature, in this way, the xz coordinate information of each node is used as the two-dimensional coordinate information of the Point xy to be passed into heatmapjs, and the elevation of the three-dimensional node is also the Y axis information, which is used as the distance information from the ground, the larger the distance, the smaller the value to be passed into heatmapjs. At last, start the Three-Dimensional Topology Auto-layout elastic algorithm of HT for Web, in this way, you can intuitively observe the temperature and heat map changes of the floor when the node is dynamically changing in different spatial locations.
The core of the code is to reload forceLayout. the onRelaxed function builds the information of all heat source nodes into the data required by heatmap during each Automatic Layout Process, and uses ht. default. setImage ('hm-bottom ', heatmap. _ renderer. canvas); register the canvas of the heat map as the HT image, and the floor elements of the floor are bound to the registered 'hm-bottom 'image, so that the canvas can be drawn in memory, then, we use the 3D engine of HT for Web to dynamically present the effect of Cavnas as texture information to 3D scenes.
The entire implementation code is less than a hundred lines below. You can also use commit!
- MAX = 500;
- WIDTH = 1024;
- HEIGHT = 512;
- function init() {
- dataModel = new ht.DataModel();
- g3d = new ht.graph3d.Graph3dView(dataModel);
- g3d.getMoveMode = function(e){ return 'xyz'; };
- view = g3d.getView();
- view.className = 'main';
- document.body.appendChild(view);
- window.addEventListener('resize', function (e) { g3d.invalidate(); }, false);
- heatmap = h337.create({ width: WIDTH, height: HEIGHT });
- ht.Default.setImage('hm-bottom', heatmap._renderer.canvas);
- var floor = new ht.Node();
- floor.s3(WIDTH, 1, HEIGHT);
- 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
- });
- dataModel.add(floor);
- var root = createNode();
- for (var i = 0; i < 3; i++) {
- var iNode = createNode();
- createEdge(root, iNode);
- for (var j = 0; j < 3; j++) {
- var jNode = createNode();
- createEdge(iNode, jNode);
- }
- }
- forceLayout = new ht.layout.Force3dLayout(g3d);
- forceLayout.start();
- forceLayout.onRelaxed = function(){
- var points = [];
- dataModel.each(function(data){
- if(data instanceof ht.Node && data !== floor){
- var p3 = data.p3();
- if(p3[1] > MAX){
- p3[1] = MAX;
- data.setElevation(MAX);
- }
- else if(p3[1] < -MAX){
- p3[1] = -MAX;
- data.setElevation(-MAX);
- }
- points.push({
- x: p3[0] + WIDTH/2,
- y: p3[2] + HEIGHT/2,
- value: MAX - Math.abs(p3[1])
- });
- }
- });
- heatmap.setData({data: points, min: 0, max: MAX});
- };
- }
- function createNode(){
- var node = new ht.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(node);
- return node;
- }
- function createEdge(sourceNode, targetNode){
- var edge = new ht.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(edge);
- return edge;
- }