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
或者外链引入!(建议下载,运行速度更快~)
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>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); }右图是配置了半径:
修改了画布颜色,点大小等: 源码:
<!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 结合热力图这里我以动态热力图为目标,开始学习: (多图数据刷新,模拟动态效果,下方可选择倍数查看)
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>主要是捕捉鼠标移动效果,再绘图:
<!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 & 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>大致就是这样,今日学习完工! 😃
