heatmap.js来绘制热力图

mac2026-04-14  2

Heatmap.js

一、简介二、使用2.1 上手2.2 设置点的半径2.3 添加底图2.4 更多 三、高级用法3.1 动态热力图3.2 鼠标跟随热力图3.3 显示数值

一、简介

Heatmap.js V2.0 是目前网络上最先进的热图可视化库。新的2.0版本 Heatmap.js 更快,拥有更强的渲染模块,使用更方便,因此您可以快速掌握和扩展自定义功能。

参考链接:

官方文档【JS】heatmap.js v2.0,详细参数总结

二、使用

😃 先下载js使用 😃

原文:https://github.com/pa7/heatmap.js/blob/master/build/heatmap.js

或者外链引入!(建议下载,运行速度更快~)

2.1 上手

初始化实例,heatmapInstance给实例设置数据(随机点) 简单教程:Minimal Configuration Example

Tips:获取文档中class="example"的第一个元素: document.querySelector(".example");

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>HeadMap.js</title> <!--Framework--> <script src="js/heatmap.js" type="text/javascript"></script> </head> <body> <h1>HeadMap</h1> <div class="heatmap" style="height: 600px;width: 500px;"></div> <script type="text/javascript"> // minimal heatmap instance configuration var heatmapInstance = h337.create({ // only container is required, the rest will be defaults //只需要一个container,也就是最终要绘制图形的dom节点,其他都默认 container: document.querySelector('.heatmap') }); // now generate some random data var points = []; var max = 0; var width = 840; var height = 400; var len = 200; while (len--) { var val = Math.floor(Math.random()*100); max = Math.max(max, val); var point = {//这里可以自定义 x: Math.floor(Math.random()*width), y: Math.floor(Math.random()*height), value: val }; points.push(point); } // heatmap data format var data = { max: max,//所有数据中的最大值 data: points//最终要展示的数据 }; // if you have a set of datapoints always use setData instead of addData // for data initialization heatmapInstance.setData(data); </script> </body> </html>

2.2 设置点的半径

point 配置点的半径:radius: radius

var point = { x: Math.floor(Math.random()*width), y: Math.floor(Math.random()*height), value: val, // radius configuration on point basis 主要是半径的配置, radius: radius }; points.push(point); }

右图是配置了半径:

2.3 添加底图

<div class="heatmap" style=" width:700px; height: 600px;"> <img src="img/classroom.png" style="width:100%; height: 100%"> </div>

2.4 更多

修改了画布颜色,点大小等: 源码:

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>HeadMap.js</title> <!--Framework--> <script src="js/jquery-3.4.1.min.js" type="text/javascript"></script> <script src="js/heatmap.js" type="text/javascript"></script> </head> <body> <h1>HeadMap</h1> <div class="heatmap" style="height: 600px;width: 500px;"></div> <script type="text/javascript"> // customized heatmap configuration var heatmapInstance = h337.create({ // required container container: document.querySelector('.heatmap'), // backgroundColor to cover transparent areas 背景颜色,可以覆盖透明区域 backgroundColor: 'rgba(0,0,0,.95)', // custom gradient colors 这里设置了颜色梯度。键值从0到1 gradient: { // enter n keys between 0 and 1 here // for gradient color customization '.5': 'blue', '.8': 'red', '.95': 'white' }, // the maximum opacity (the value with the highest intensity will have it) 最高透明度 maxOpacity: .9, // minimum opacity. any value > 0 will produce // no transparent gradient transition minOpacity: .3 }); // now generate some random data var points = []; var max = 0; var width = 540; var height = 600; var len = 300; while (len--) { var val = Math.floor(Math.random()*100); var radius = Math.floor(Math.random()*70); max = Math.max(max, val); var point = { x: Math.floor(Math.random()*width), y: Math.floor(Math.random()*height), value: val, radius: radius }; points.push(point); } // heatmap data format var data = { max: max, data: points }; // if you have a set of datapoints always use setData instead of addData // for data initialization heatmapInstance.setData(data); </script> </body> </html>

三、高级用法

参考官方文档,大概如下函数(命名即使用方法),具体使用见example:

官方文档:heatmap.js Documentation

总共有两个对象: h337是heatmap的全局变量, 而heatmapInstance是h337实例化的对象

😃 划重点 😃

官方示例:heatmap.js Examples

根据官方示例,画轮子造车,这里有:

动态热力图基础热力图(basic example也就是我们之前说的)鼠标跟随热力图谷歌地图结合热力图AngularJS 结合热力图

3.1 动态热力图

这里我以动态热力图为目标,开始学习: (多图数据刷新,模拟动态效果,下方可选择倍数查看)

headMap.js用法与前文相同,这里引入了canvas画布作为动图演示模块,引入了原文的example-commons.css样式,效果实现。

源码:

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>HeadMap.js</title> <!-- 动图效果样式 --> <link rel="stylesheet" href="https://www.patrick-wied.at/static/heatmapjs/assets/css/commons.css"> <link rel="stylesheet" href="https://www.patrick-wied.at/static/heatmapjs/assets/css/example-commons.css"> <!--Framework--> <script src="js/heatmap.js" type="text/javascript"></script> <style> .demo-wrapper { position: relative; } /* animation player css */ .timeline-wrapper { position: absolute; top: 10px; left: 10px; right: 10px; height: 30px; background: white; transition: 1s ease all; border-radius: 4px; box-shadow: 0 1px 5px rgba(0, 0, 0, .65) } .heatmap-timeline { position: absolute; top: 0; right: 15px; left: 80px; height: 100%; } .heatmap-timeline .line { position: absolute; left: 0; right: 0; top: 15px; height: 2px; background: #d7d7d7; } .heatmap-timeline .time-point.active { background: black; } .heatmap-timeline .time-point { position: absolute; background: white; border: 2px solid #272727; width: 8px; height: 8px; border-radius: 100%; cursor: pointer; top: 15px; transform: translateX(-50%) translateY(-50%); } .heatmap-timeline .time-point:hover { box-shadow: 0 0 5px black; } .timeline-wrapper button { position: absolute; outline: none; color: black; background: #f2f2f2; width: 65px; height: 100%; cursor: pointer; border: none; text-transform: uppercase; border-top-left-radius: 3px; border-bottom-left-radius: 3px; } .heatmap-timeline .time-point.active { background: black; } /* end animation player css */ </style> </head> <body> <h1>HeadMap</h1> <div class="wrapper"> <div class="demo-wrapper"> <div class="heatmap" style="position: relative;"> <canvas class="heatmap-canvas" width="834" height="400" style="position: absolute; left: 0px; top: 0px;"> </canvas> </div> <div class="timeline-wrapper"> <button>play</button> <div class="heatmap-timeline"> <div class="line"></div> <div class="time-point" style="left: 0%;"></div> <div class="time-point" style="left: 5.26316%;"></div> <div class="time-point" style="left: 10.5263%;"></div> <div class="time-point" style="left: 15.7895%;"></div> <div class="time-point" style="left: 21.0526%;"></div> <div class="time-point active" style="left: 26.3158%;"></div> <div class="time-point" style="left: 31.5789%;"></div> <div class="time-point" style="left: 36.8421%;"></div> <div class="time-point" style="left: 42.1053%;"></div> <div class="time-point" style="left: 47.3684%;"></div> <div class="time-point" style="left: 52.6316%;"></div> <div class="time-point" style="left: 57.8947%;"></div> <div class="time-point" style="left: 63.1579%;"></div> <div class="time-point" style="left: 68.4211%;"></div> <div class="time-point" style="left: 73.6842%;"></div> <div class="time-point" style="left: 78.9474%;"></div> <div class="time-point" style="left: 84.2105%;"></div> <div class="time-point" style="left: 89.4737%;"></div> <div class="time-point" style="left: 94.7368%;"></div> <div class="time-point" style="left: 100%;"></div> </div> </div> </div> <div class="demo-controls"> <button class="trigger-refresh btn" data-fps="10">Set speed to 10 frames per second</button> <button class="trigger-refresh btn" data-fps="5">Set speed to 5 frames per second</button> <button class="trigger-refresh btn" data-fps="1">Set speed to 1 frame per second</button> <br style="clear:both"> </div> </div> <script type="text/javascript"> window.onload = function() { function generateRandomData(len) { // generate some random data var points = []; var max = 0; var width = 840; var height = 400; while (len--) { var val = Math.floor(Math.random() * 100); max = Math.max(max, val); var point = { x: Math.floor(Math.random() * width), y: Math.floor(Math.random() * height), value: val }; points.push(point); } var data = { max: max, data: points }; return data; } function $(selector) { return document.querySelectorAll(selector); } function AnimationPlayer(options) { this.heatmap = options.heatmap; this.data = options.data; this.interval = null; this.animationSpeed = options.animationSpeed || 300; this.wrapperEl = options.wrapperEl; this.isPlaying = false; this.init(); }; AnimationPlayer.prototype = { init: function() { var dataLen = this.data.length; this.wrapperEl.innerHTML = ''; var playButton = this.playButton = document.createElement('button'); playButton.onclick = function() { if (this.isPlaying) { this.stop(); } else { this.play(); } this.isPlaying = !this.isPlaying; }.bind(this); playButton.innerText = 'play'; this.wrapperEl.appendChild(playButton); var events = document.createElement('div'); events.className = 'heatmap-timeline'; events.innerHTML = '<div class="line"></div>'; for (var i = 0; i < dataLen; i++) { var xOffset = 100 / (dataLen - 1) * i; var ev = document.createElement('div'); ev.className = 'time-point'; ev.style.left = xOffset + '%'; ev.onclick = (function(i) { return function() { this.isPlaying = false; this.stop(); this.setFrame(i); }.bind(this); }.bind(this))(i); events.appendChild(ev); } this.wrapperEl.appendChild(events); this.setFrame(0); }, play: function() { var dataLen = this.data.length; this.playButton.innerText = 'pause'; this.interval = setInterval(function() { this.setFrame(++this.currentFrame % dataLen); }.bind(this), this.animationSpeed); }, stop: function() { clearInterval(this.interval); this.playButton.innerText = 'play'; }, setFrame: function(frame) { this.currentFrame = frame; var snapshot = this.data[frame]; this.heatmap.setData(snapshot); var timePoints = $('.heatmap-timeline .time-point'); for (var i = 0; i < timePoints.length; i++) { timePoints[i].classList.remove('active'); } timePoints[frame].classList.add('active'); }, setAnimationData: function(data) { this.isPlaying = false; this.stop(); this.data = data; this.init(); }, setAnimationSpeed: function(speed) { this.isPlaying = false; this.stop(); this.animationSpeed = speed; } }; var heatmapInstance = h337.create({ container: document.querySelector('.heatmap') }); // animationData contains an array of heatmap states var animationData = []; for (var i = 0; i < 20; i++) { animationData.push(generateRandomData(300)); } var player = new AnimationPlayer({ heatmap: heatmapInstance, wrapperEl: document.querySelector('.timeline-wrapper'), data: animationData, animationSpeed: 500 }); var controlButtons = $('.trigger-refresh'); for (var i = 0; i < controlButtons.length; i++) { controlButtons[i].onclick = function() { var fps = this.dataset.fps; player.setAnimationSpeed(1 / (+fps) * 1000); }; } }; </script> </body> </html>

3.2 鼠标跟随热力图

主要是捕捉鼠标移动效果,再绘图:

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>HeadMap.js</title> <!-- 动图效果样式 --> <link rel="stylesheet" href="https://www.patrick-wied.at/static/heatmapjs/assets/css/commons.css"> <link rel="stylesheet" href="https://www.patrick-wied.at/static/heatmapjs/assets/css/example-commons.css"> <!--Framework--> <script src="js/heatmap.js" type="text/javascript"></script> <style> .demo-wrapper { position:relative; background:rgba(0,0,0,.9); } .text-bg { color:rgba(255,255,255,.8); position:absolute; left:0; top:0; right:0; bottom:0; height:40px; width:230px; text-align:center; margin:auto; } </style> </head> <body> <h1>HeadMap</h1> <div class="wrapper"> <div class="demo-wrapper"> <div class="text-bg"> much interesting click &amp; move zone here! </div> <div class="heatmap" style="position: relative;"> <canvas class="heatmap-canvas" width="834" height="400" style="position: absolute; left: 0px; top: 0px;"> </canvas> </div> </div> </div> <script type="text/javascript"> window.onload = function() { var heatmapContainer = document.querySelector('.heatmap'); var heatmapInstance = h337.create({ container: heatmapContainer, radius: 50 }); heatmapContainer.onmousemove = heatmapContainer.ontouchmove = function(e) { // we need preventDefault for the touchmove e.preventDefault(); var x = e.layerX; var y = e.layerY; if (e.touches) { x = e.touches[0].pageX; y = e.touches[0].pageY; } heatmapInstance.addData({ x: x, y: y, value: 1 }); }; heatmapContainer.onclick = function(ev) { heatmapInstance.addData({x: ev.layerX, y: ev.layerY, value:1 }); }; }; </script> </body> </html>

3.3 显示数值

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>HeadMap.js</title> <!-- 动图效果样式 --> <link rel="stylesheet" href="https://www.patrick-wied.at/static/heatmapjs/assets/css/commons.css"> <link rel="stylesheet" href="https://www.patrick-wied.at/static/heatmapjs/assets/css/example-commons.css"> <!--Framework--> <script src="js/heatmap.js" type="text/javascript"></script> <style> .legend-area { position:absolute; bottom:0; right:0; padding:10px; background:white; outline:3px solid black; line-height:1em; } h4 { margin:0; padding:0; margin-bottom:5px;} #min { float:left; } #max { float:right; } span { font-size:14px; margin:0; padding:0; } .tooltip { position:absolute; left:0; top:0; background:rgba(0,0,0,.8); color:white; font-size:14px; padding:5px; line-height:18px; display:none;} .demo-wrapper { position:relative; } </style> </head> <body> <h1>HeadMap</h1> <div class="wrapper"> <div class="demo-wrapper"> <div class="heatmap" style="position: relative;"> <canvas class="heatmap-canvas" width="834" height="400" style="position: absolute; left: 0px; top: 0px;"></canvas></div> <div class="tooltip" style="display: none; transform: translate(538px, 377px);">633</div> <div class="legend-area"> <h4>Legend Title</h4> <span id="min">0</span> <span id="max">1224</span> <img id="gradient" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAKCAYAAABCHPt+AAAAx0lEQVRYR+2WwQqDMBBEn2SF6P9/Z9tTFRSULVkIpdC0kBUxgTDZax4zsx1sG7WPrDDMECdXFVkYgAiuKjNwB27AI70L584HyOIKwsCLrK4gDLxMGQQFomAUiN4vcwNSwUF/AUmgGpDaQMwZheoDpF8gpg4ZkzrMGllj+nCNE70ec8gjqxCERZoPELlYhzyzrrDOKFQfIOqQA7asPhxT6uEUQBwi6rVdZZH4KbI81mBRIIVb1fvW1RxSodTP4ZCrRdaPZW6O2gEogeBRRgNVBwAAAABJRU5ErkJggg==" style="width:100%"> </div> </div> <div class="demo-controls"> <button class="trigger-refresh btn">re-generate data</button> <br style="clear:both"> </div> </div> <script type="text/javascript"> window.onload = function() { function generateRandomData(len) { // generate some random data var points = []; var max = 0; var min = 1234; var width = 840; var height = 400; while (len--) { var val = Math.floor(Math.random()*1234); max = Math.max(max, val); min = Math.min(min, val); var point = { x: Math.floor(Math.random()*width), y: Math.floor(Math.random()*height), value: val }; points.push(point); } var data = { max: max, min:min, data: points }; return data; }; /* legend code */ // we want to display the gradient, so we have to draw it var legendCanvas = document.createElement('canvas'); legendCanvas.width = 100; legendCanvas.height = 10; var min = document.querySelector('#min'); var max = document.querySelector('#max'); var gradientImg = document.querySelector('#gradient'); var legendCtx = legendCanvas.getContext('2d'); var gradientCfg = {}; function updateLegend(data) { // the onExtremaChange callback gives us min, max, and the gradientConfig // so we can update the legend min.innerHTML = data.min; max.innerHTML = data.max; // regenerate gradient image if (data.gradient != gradientCfg) { gradientCfg = data.gradient; var gradient = legendCtx.createLinearGradient(0, 0, 100, 1); for (var key in gradientCfg) { gradient.addColorStop(key, gradientCfg[key]); } legendCtx.fillStyle = gradient; legendCtx.fillRect(0, 0, 100, 10); gradientImg.src = legendCanvas.toDataURL(); } }; /* legend code end */ var heatmapInstance = h337.create({ container: document.querySelector('.heatmap'), onExtremaChange: function(data) { updateLegend(data); } }); // generate 200 random datapoints var data = generateRandomData(200); heatmapInstance.setData(data); var demoWrapper = document.querySelector('.demo-wrapper'); var tooltip = document.querySelector('.tooltip'); function updateTooltip(x, y, value) { // + 15 for distance to cursor var transform = 'translate(' + (x + 15) + 'px, ' + (y + 15) + 'px)'; tooltip.style.MozTransform = transform; /* Firefox */ tooltip.style.msTransform = transform; /* IE (9+) - note ms is lowercase */ tooltip.style.OTransform = transform; /* Opera */ tooltip.style.WebkitTransform = transform; /* Safari and Chrome */ tooltip.style.transform = transform; /* One day, my pretty */ tooltip.innerHTML = value; } demoWrapper.onmousemove = function(ev) { var x = ev.layerX; var y = ev.layerY; var value = heatmapInstance.getValueAt({ x: x, y: y }); tooltip.style.display = 'block'; updateTooltip(x, y, value); }; demoWrapper.onmouseout = function() { tooltip.style.display = 'none'; }; document.querySelector('.trigger-refresh').onclick = function() { heatmapInstance.setData(generateRandomData(200)); }; }; </script> </body> </html>

大致就是这样,今日学习完工! 😃

最新回复(0)