heatmap.js来绘制热力图

Heatmap.js

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

一、简介

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

参考链接:

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

二、使用

先下载js使用

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

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

2.1 上手

  • 初始化实例,heatmapInstance
  • 给实例设置数据(随机点)
    heatmap.js来绘制热力图_第1张图片
    简单教程:Minimal Configuration Example

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>

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);
}

右图是配置了半径:
heatmap.js来绘制热力图_第2张图片heatmap.js来绘制热力图_第3张图片

2.3 添加底图

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

heatmap.js来绘制热力图_第4张图片

2.4 更多

修改了画布颜色,点大小等:
heatmap.js来绘制热力图_第5张图片
源码:


<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:

官方文档:heatmap.js Documentation
heatmap.js来绘制热力图_第6张图片

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

划重点

官方示例:heatmap.js Examples

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

  • 动态热力图
  • 基础热力图(basic example也就是我们之前说的)
  • 鼠标跟随热力图
  • 谷歌地图结合热力图
  • AngularJS 结合热力图
    heatmap.js来绘制热力图_第7张图片

3.1 动态热力图

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

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>

3.2 鼠标跟随热力图

主要是捕捉鼠标移动效果,再绘图:
heatmap.js来绘制热力图_第8张图片


<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>

3.3 显示数值

heatmap.js来绘制热力图_第9张图片


<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>

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

你可能感兴趣的:(#,JavaScript)