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");
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HeadMap.jstitle>
<script src="js/heatmap.js" type="text/javascript">script>
head>
<body>
<h1>HeadMaph1>
<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);
}
<div class="heatmap" style=" width:700px; height: 600px;">
<img src="img/classroom.png" style="width:100%; height: 100%">
div>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HeadMap.jstitle>
<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>HeadMaph1>
<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:
总共有两个对象: h337是heatmap的全局变量, 而heatmapInstance是h337实例化的对象
划重点
官方示例:heatmap.js Examples
根据官方示例,画轮子造车,这里有:
这里我以动态热力图
为目标,开始学习:
(多图数据刷新,模拟动态效果,下方可选择倍数查看)
headMap.js用法与前文相同,这里引入了
canvas
画布作为动图演示模块,引入了原文的example-commons.css
样式,效果实现。
源码:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HeadMap.jstitle>
<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">
<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>HeadMaph1>
<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>playbutton>
<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 secondbutton>
<button class="trigger-refresh btn" data-fps="5">Set speed to 5 frames per secondbutton>
<button class="trigger-refresh btn" data-fps="1">Set speed to 1 frame per secondbutton>
<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 = '';
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>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HeadMap.jstitle>
<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">
<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>HeadMaph1>
<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>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HeadMap.jstitle>
<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">
<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>HeadMaph1>
<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);">633div>
<div class="legend-area">
<h4>Legend Titleh4>
<span id="min">0span>
<span id="max">1224span>
<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 databutton>
<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>
大致就是这样,今日学习完工!