<template>
<div>
<canvas :width="widthPal" :height="heightPal" id="canvas_01"></canvas>
<canvas
:width="widthImg"
:height="heightImg"
id="canvas_02"
style="background-color: #fff; margin-left: 20px"
></canvas>
</div>
</template>
<script>
export default {
data () {
return {
data: [
{ x: 471, y: 277, value: 25 },
{ x: 438, y: 375, value: 97 },
{ x: 373, y: 19, value: 71 },
{ x: 473, y: 42, value: 63 },
{ x: 463, y: 95, value: 97 },
{ x: 590, y: 437, value: 34 },
{ x: 377, y: 442, value: 66 },
{ x: 171, y: 254, value: 20 },
{ x: 6, y: 582, value: 64 },
{ x: 387, y: 477, value: 14 },
{ x: 300, y: 300, value: 80 },
{ x: 40, y: 40, value: 18 },
{ x: 80, y: 40, value: 19 },
],
defaultColorStops: {
0: "#0ff",
0.2: "#0f0",
0.4: "#ff0",
1: "#f00",
},
// 图例
widthPal: 20,
heightPal: 256,
// 热力图范围
widthImg: 600,
heightImg: 600,
radius: 40, // 径向渐变半径
// 热力图代表的最大最小值
max: 10,
min: 5,
imageData: null,
alpha: null
}
},
mounted () {
this.init();
this.draw();
},
methods: {
init () {
const colorStops = this.defaultColorStops;
// 创建canvas
const canvas = document.getElementById("canvas_01");
const ctx = canvas.getContext("2d");
// 创建线性渐变色
const linearGradient = ctx.createLinearGradient(0, 0, 0, this.heightPal);
for (const key in colorStops) {
linearGradient.addColorStop(key, colorStops[key]);
}
// 绘制渐变色条
ctx.fillStyle = linearGradient;
ctx.fillRect(0, 0, this.widthPal, this.heightPal);
// 读取像素数据
this.imageData = ctx.getImageData(0, 0, 1, this.heightPal).data;
this.canvas = canvas;
},
/**
* 取色器
* @param {Number} position 像素位置
* @return {Array.<Number>} [r, g, b]
*/
colorPicker (position) {
return this.imageData.slice(position * 4, position * 4 + 3);
},
draw () {
const radius = this.radius
const max = this.max
const min = this.min
const canvas = document.getElementById("canvas_02");
// canvas.width = this.width;
// canvas.height = this.height;
const context = canvas.getContext("2d");
this.data.forEach(point => {
const { x, y, value } = point;
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI);
context.closePath();
// 创建渐变色: r,g,b取值比较自由,我们只关注alpha的数值
const radialGradient = context.createRadialGradient(x, y, 0, x, y, radius);
radialGradient.addColorStop(0.0, "rgba(0,0,0,1)");
radialGradient.addColorStop(1.0, "rgba(0,0,0,0)");
context.fillStyle = radialGradient;
// 设置globalAlpha: 需注意取值需规范在0-1之间
const globalAlpha = (value - min) / (max - min);
context.globalAlpha = Math.max(Math.min(globalAlpha, 1), 0);
// 填充颜色
context.fill();
// 像素着色
// tips: ImageData 对象中每一个像素
// red = imgData.data[0];
// green = imgData.data[1];
// blue = imgData.data[2];
// alpha = imgData.data[3];
const imageData = context.getImageData(0, 0, this.widthImg, this.heightImg);
const data = imageData.data;
for (var i = 3; i < data.length; i += 4) {
const alpha = data[i];
const color = this.colorPicker(alpha);
data[i - 3] = color[0];
data[i - 2] = color[1];
data[i - 1] = color[2];
}
context.putImageData(imageData, 0, 0);
});
}
}
}
</script>
vue 项目中画热力图
最新推荐文章于 2024-02-06 14:19:52 发布