基于canvas实现温度热力图,温度云图(一)--实现温度分布图

canvas实现温度热力图、温度分布图。现在市场上的热力图都是根据同一点的数量来表示当前点的热度。随着物联网温度传感器的使用,越来越多的业务开始监控一个平面或者一个区域的温度,然而这种监控的可视化是现在的echarts也没有提供很好的表现形式。我就自己研究了一下,简单实现一下,温度分布图。

本专题将持续更新:

基于canvas实现温度热力图,温度云图(一)--实现温度分布图

基于canvas实现温度热力图,温度云图(二)--增加提示框

下面是效果图

canvas实现

第一步 获取canvas的dom
 

在项目合适的位置加入canvas画布,获取画布的dom,本demo目前为js实现,vue中请自行解决,后续会更新。

<canvas id="canvas" width="600" height="600px"></canvas>


var canvas= document.getElementById("canvas");
var context = canvas.getContext("2d");

第二步 准备数据


这里我准备了30个点5*6的矩形数据,图像的放大比例,也就是每个点的间隔,通过自己canvas画布的大小按比例进行调整。
 

var xData = [{
      "x": 1,
      "y": 1,
      "measValue": 15.57
    },{
      "x": 2,
      "y": 1,
      "measValue": 14.3
    }, {
      "x": 3,
      "y": 1,
      "measValue": 23.67
    }, {
      "x": 4,
      "y": 1,
      "measValue": 28.5
    }, {
      "x": 5,
      "y": 1,
      "measValue": 14.54
    }, {
      "x": 5,
      "y": 2,
      "measValue": 12.44
    }, {
      "x": 4,
      "y": 2,
      "measValue": 23.04
    }, {
      "x": 3,
      "y": 2,
      "measValue": 20.11
    }, {
      "x": 2,
      "y": 2,
      "measValue": 15.08
    }, {
      "x": 1,
      "y": 2,
      "measValue": 19.71
    }, {
      "x": 1,
      "y": 3,
      "measValue": 23.47
    },  {
      "x": 2,
      "y": 3,
      "measValue": 15.51
    }, {
      "x": 3,
      "y": 3,
      "measValue": 13.98
    },  {
      "x": 4,
      "y": 3,
      "measValue": 22.78
    },  {
      "x": 5,
      "y": 3,
      "measValue": 22.63
    },  {
      "x": 5,
      "y": 4,
      "measValue": 15.41
    }, {
      "x": 4,
      "y": 4,
      "measValue": 14.22
    }, {
      "x": 3,
      "y": 4,
      "measValue": 23.2
    }, {
      "x": 2,
      "y": 4,
      "measValue": 20.51
    }, {
      "x": 1,
      "y": 4,
      "measValue": 13.76
    }, {
      "x": 1,
      "y": 5,
      "measValue": 20.04
    }, {
      "x": 2,
      "y": 5,
      "measValue": 22.95
    }, {
      "x": 3,
      "y": 5,
      "measValue": 12.73
    },  {
      "x": 4,
      "y": 5,
      "measValue": 15.19
    },  {
      "x": 5,
      "y": 5,
      "measValue": 22.51
    }, {
      "x": 5,
      "y": 6,
      "measValue": 22.28
    }, {
      "x": 4,
      "y": 6,
      "measValue": 13.22
    }, {
      "x": 3,
      "y": 6,
      "measValue": 14.44
    }, {
      "x": 2,
      "y": 6,
      "measValue": 23.06
    }, {
      "x": 1,
      "y": 6,
      "measValue": 19.13
    }];
    
    
var circles = [];//准备一个数组后续会用到

for (var i = 0; i < xData.length; i++) {
    //这里将横纵坐标进行放大,可以根据自己需求进行调节
    var x = xData[i].x*70+80;
    var y = (height - xData[i].y*70)-70;//height为canvas高度
    var value = xData[i].measValue;
    
    circles.push({
      x : x ,
      y : y ,
      radius : 20,
      value : value,
      text : xData[i].x + '行' +xData[i].y +'列,温度:'+value
    });
}

第三步 开始画点

以坐标点画圆,也需要根据上一步中的间隔,合理调整圆的半径大小,其中max和min是最高温和最低温,此demo中以30°为最高温,可以根据自己项目不同来调整温度的最大值。注意:温度最大值是代表的颜色最大值,而不是你所有环境温度的最大值。

circles.forEach(point => {
    let {x, y, value} = point; 
    let radius = 125;//圆的大小
    let max = 30;//最高温度,我这里设置30°
    let min = 0;//最低温度,我这里设置30°

    let stopColor;
    if (value>15){
       stopColor = (value - min) / (max - min);
    }else{
       stopColor = (value - min) / (max - min);
    }

    context.beginPath();
    context.arc(x, y,  radius, 0, 2 * Math.PI);
    context.closePath();

    // 创建渐变色: r,g,b取值比较自由,我们只关注alpha的数值
    let radialGradient = context.createRadialGradient(x, y, 0, x, y, radius);
    radialGradient.addColorStop(0.0, "rgba(0,0,0,"+stopColor+")");
    radialGradient.addColorStop(stopColor, "rgba(0,0,0,0)");
    context.fillStyle = radialGradient;

    context.fill();
});


效果图如下

第四步 通过绘制渐变色取色 重新渲染

通过定义的渐变色区间进行取色,渐变色设置在下面的tempMap.js中可以修改,0-1代表最低到最高的颜色,根据第三步中的最高温以及百分比,可以算出临界点的温度颜色。比如30度的0.4就是12°时的温度颜色

var tempMap = new TempMap();//在下面会给出

let imageData = context.getImageData(0, 0, width, height);
let data2 = imageData.data;
for (var i = 3; i < data2.length; i+=4) {
    let alpha = data2[i];
    let color = tempMap.colorPicker(alpha);
    data2[i - 3] = color[0];
    data2[i - 2] = color[1];
    data2[i - 1] = color[2];
}
context.putImageData(imageData, 0, 0);


完成啦

渐变色js实现

tempMap.js

以下是完整版的js代码

(function () {
    const defaultColorStops = {
        0: "#0000ff",
        0.4: "#0000ff",
        0.6: "#0f0",
        0.8: "#ff0",
        1: "#f00",
    };

    const width = 20, height = 256;

    function TempMap(opts) {
        Object.assign(this, opts);
        this.init();
    }

    TempMap.prototype.init = function() {
        let colorStops = this.colorStops || defaultColorStops;

        // 创建canvas
        let canvas = document.createElement("canvas");
        canvas.width = width;
        canvas.height = height;
        let ctx = canvas.getContext("2d");

        // 创建线性渐变色
        let linearGradient = ctx.createLinearGradient(0, 0, 0, height);
        for (const key in colorStops) {
            linearGradient.addColorStop(key, colorStops[key]);
        }

        // 绘制渐变色条
        ctx.fillStyle = linearGradient;
        ctx.fillRect(0, 0, width, height);

        // 读取像素数据
        this.imageData = ctx.getImageData(0, 0, 1, height).data;
        this.canvas = canvas;
    };

    /**
     * 取色器
     * @param {Number} position 像素位置
     * @return {Array.<Number>} [r, g, b]
     */
    TempMap.prototype.colorPicker = function(position) {
        return this.imageData.slice(position * 4, position * 4 + 3);
    };

    // amd
    if (typeof define !== 'undefined' && define.amd) define(function () {
        return TempMap;
    });
    // common js
    if (typeof exports !== 'undefined') exports.TempMap = TempMap;
    // browser
    else if (typeof window !== 'undefined') window.TempMap = TempMap;
    // nodejs
    if (typeof module !== 'undefined') {
        module.exports = TempMap;
    }

}());

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

似一筷扣肉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值