最近做一個(gè)項(xiàng)目骡和,需要繪制熱力圖,但是發(fā)覺現(xiàn)成的庫封裝都很不靈活
heatmap.js
百度Echarts
等都有封裝
參考百度echarts的熱力圖插件静浴,我整理了一下繪制熱力圖的思路
數(shù)據(jù)構(gòu)成
[[x, y, cnt], [x, y, cnt]]
// x y 表示這個(gè)點(diǎn)在canvas上的位置
對(duì)canvas的簡單封裝
function Canvas(w, h) {
this.canvas = document.createElement('canvas')
this.canvas.width = w
this.canvas.height = h
}
Canvas.prototype.getContext = function() {
return this.canvas.getContext('2d')
}
Canvas.prototype.getCanvas = function(){
return this.canvas
}
創(chuàng)建canvas的每個(gè)點(diǎn)的漸變色
function creatHeadtMapCircle(size) {
const shadowBlur = size / 2
const r = size + shadowBlur
const offsetDistance = 1000
const circle = new Canvas(r * 2, r * 2)
let ctx = circle.getContext()
ctx.shadowBlur = shadowBlur
ctx.shadowColor = 'black'
ctx.shadowOffsetX = ctx.shadowOffsetY = offsetDistance
ctx.beginPath()
ctx.arc( r - offsetDistance, r2 - offsetDistance, size, 0, Mathi.PI * 2 , true)
ctx.closePath()
ctx.fill()
return circle
}
繪制單個(gè)點(diǎn)的結(jié)果
繪制多個(gè)點(diǎn),根據(jù)權(quán)重值挤渐,可以得到如下的圖形苹享, 不同的權(quán)重 設(shè)置不同的透明度
創(chuàng)一個(gè)顏色映射
class ColorRange {
constructor (options) {
this.gradient = options.gradient || {
0.25: 'rgba(0, 0, 255, 1)',
0.55: 'rgba(0, 255, 0, 1)',
0.85: 'rgba(255, 255, 0, 1)',
1.0: 'rgba(255, 0, 0, 1)'
}
this.max = options.max || 30
this.min = options.min || 0
this.initPalette()
}
initPalette () {
const gradient = this.gradient
const canvas = new Canvas(256, 1)
const ctx = this.ctx = canvas.getContext()
const lineGradient = ctx.createLinearGradient(0, 0, 256, 1)
for (let key in gradient) {
lineGradient.addColorStop(parseFloat(key), gradient[key])
}
ctx.fillStyle = lineGradient
ctx.fillRect(0, 0, 256, 1)
}
getImageData (v ) {
const imageData = this.ctx,getImageData(0, 0, 256, 1).data
if (v === undefined) return imageData
if (v > this.max) v = this.max
if (v < this.min ) v = this.min
var index = Math.floor((v - min) / (max - min) * 255 ) * 4
return [imageData[index], imageData[index + 1], imageData[index + 2], imageData[index + 3]]
}
}
顏色映射
根據(jù)不同的繪圖結(jié)果把不同的顏色透明度,映射到不同的顏色上浴麻,得到色彩圖
let colored = sctx.getImageData(0, 0, canvas.width, canvas.height)
let gradient = (new ColorRange()).getImageData()
const opacity = 0.8
for(let i = 0, len = colored.data.length, j; i < len; i += 4) {
j = colored.data[i] * 4
if (colored.data[i] / 256 > opacity) colored.data[i] = 256 * opacity
colored.data[i - 3] = gradient[j]
colored.data[i - 2] = gradient[j + 1]
colored.data[i - 1] = gradient[j + 2]
}
ctx.putImageData(colored, 0, 0)
最后整理成一個(gè)快速好用的庫得问,提供給大家