2021-12-24
Heatmap.js 是目前应用最广的web动态热图javaScript库。heatmap使用 canvas 进行绘制。
一、传送门
Heatmap官网:
github下载:
二、代码结构
1、整个js库包裹在一个立即执行的匿名函数里,以避免污染全局命名空间。这也是很多js库的常见写法。
2、核心对象有三个:Store(数据)、Canvas2dRenderer(绘制工具)、HeatMap(构建器)。
3、通过global【'h337'】暴露创建工厂。
三、热力图渲染原理
以 heatmap.js v2.0.5 为例子; heatmap使用 canvas 进行绘制。
Heatmap.js 最重要的4个点: _getPointTemplate, _getColorPalette , _drawAlpha , _colorize
3.1、点模板 _getPointTemplate,设置单点渲染模板
点模板对应热力图数据点。它是一个圆点,根据可配置的模糊因子(blurFactor,默认.85),可使圆点带有模糊效果(借助createRadialGradient)。
主要是调用 canvas 的 createRadialGradient 方法。核心方法是canvas的createRadialGradient方法,每个点设置渲染半径,由渐变因子 blur 确定内圆比例,内圆与外圆的圆周间进行无色的放射渐变,达到中间透明度高,边缘透明度低的效果。这个无色的透明度渐变的圆形即为点的模板。
var _getPointTemplate = function(radius, blurFactor) {
var tplCanvas = document.createElement('canvas');
var tplCtx = tplCanvas.getContext('2d');
var x = radius;
var y = radius;
tplCanvas.width = tplCanvas.height = radius2;
if (blurFactor == 1) {
tplCtx.beginPath();
tplCtx.arc(x, y, radius, 0, 2 Math.PI, false);
tplCtx.fillStyle = 'rgba(0,0,0,1)';
tplCtx.fill();
} else {
var gradient = tplCtx.createRadialGradient(x, y, radiusblurFactor, x, y, radius);
gradient.addColorStop(0, 'rgba(0,0,0,1)');
gradient.addColorStop(1, 'rgba(0,0,0,0)');
tplCtx.fillStyle = gradient;
tplCtx.fillRect(0, 0, 2radius, 2radius);
}
return tplCanvas;
};
用 html canvas代码测试效果,代码如下:
<!DOCTYPE html
[/span>html lang="en"
[/span>head
[/span>meta charset="UTF-8"
[/span>title
[/span>style
/canvas {border:1px solid black;}/
[/span>body
[/span>div class="heatmap"
[/span>script
window.onload = function () {
var container = document.querySelector('.heatmap');
var p1 = _getPointTemplate(40, 0.85);
//document.body.appendChild(p1);
container.appendChild(p1);
}
var _getPointTemplate = function(radius, blurFactor) {
var tplCanvas = document.createElement('canvas');
var tplCtx = tplCanvas.getContext('2d');
var x = radius;
var y = radius;
tplCanvas.width = tplCanvas.height = radius2;
if (blurFactor == 1) {
tplCtx.beginPath();
tplCtx.arc(x, y, radius, 0, 2 Math.PI, false);
tplCtx.fillStyle = 'rgba(0,0,0,1)';
tplCtx.fill();
} else {
var gradient = tplCtx.createRadialGradient(x, y, radiusblurFactor, x, y, radius);
gradient.addColorStop(0, 'rgba(0,0,0,1)');
gradient.addColorStop(1, 'rgba(0,0,0,0)');
tplCtx.fillStyle = gradient;
tplCtx.fillRect(0, 0, 2radius, 2radius);
}
return tplCanvas;
};
View Code
当 radius=50, blurFactor = 0.85 ,测试效果如下:
当 radius=50, blurFactor = 0.5 ,测试效果如下:
3.2、线性色谱 _getColorPalette , 构建0到256的调色板
通过createLinearGradient你可以自主定制自己的热力图色谱(config.gradient)。
主要是调用 canvas 的 createLinearGradient 方法。核心方法是canvas的createLinearGradient方法。
var _getColorPalette = function(config) {
var gradientConfig = config.gradient || config.defaultGradient;
var paletteCanvas = document.createElement('canvas');
var paletteCtx = paletteCanvas.getContext('2d');
paletteCanvas.width = 256;
paletteCanvas.height = 1;
var gradient = paletteCtx.createLinearGradient(0, 0, 256, 1);
for (var key in gradientConfig) {
gradient.addColorStop(key, gradientConfig【key】);
}
paletteCtx.fillStyle = gradient;
paletteCtx.fillRect(0, 0, 256, 1);
return paletteCtx.getImageData(0, 0, 256, 1).data;
};
用 html canvas代码测试效果,代码如下:
<!DOCTYPE html
[/span>html lang="en"
[/span>head
[/span>meta charset="UTF-8"
[/span>title
[/span>style
/canvas {border:1px solid black;}/
[/span>body
[/span>div class="heatmap"
[/span>script
window.onload = function () {
var container = document.querySelector('.heatmap');
/var HeatmapConfig = {
defaultRadius: 40,
defaultRenderer: 'canvas2d',
defaultGradient: { 0.25: "rgb(0,0,255)", 0.55: "rgb(0,255,0)", 0.85: "yellow", 1.0: "rgb(255,0,0)"},
defaultMaxOpacity: 1,
defaultMinOpacity: 0,
defaultBlur: .85,
defaultXField: 'x',
defaultYField: 'y',
defaultValueField: 'value',
plugins: {}
};/
var config = { defaultGradient: { 0.25: "rgb(0,0,255)", 0.55: "rgb(0,255,0)", 0.85: "yellow", 1.0: "rgb(255,0,0)"} }
var imgData = _getColorPalette(config);
var c=document.createElement("canvas");
container.appendChild(c);
var ctx=c.getContext("2d");
var img = ctx.getImageData(0, 0, 256, 1)
//img.data = imgData;
for (let i = 0; i [/span> img.data.length; i++) {
img.data【i】 = imgData【i】;
}//代码效果参考:http://www.ezhiqi.com/bx/art_3057.html
ctx.putImageData(img, 0, <span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0,