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

本文介绍如何基于canvas实现温度热力图并增加提示框功能。通过监听鼠标移动事件,封装绘制方法,并实现提示框的文字显示,以增强温度分布图的交互性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

本专题将持续更新:

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

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

上一期 实现了简单的温度分布图,这次要给温度分布图加上提示框。效果如下

在这里插入图片描述

canvas监听实现

第一步 监听鼠标移动事件

用onmousemove事件监听鼠标移动事件

    //当前选中的点
    var previousSelectedCircle;
    canvas.onmousemove = onMouseMove;
    
    function onMouseMove(e) {
        //初始化选中的点
        if (previousSelectedCircle != null) {
            previousSelectedCircle.isSelected = false;
            previousSelectedCircle = null;
        }

        var rect = canvas.getBoundingClientRect(); 
        //获取的是样式,需要转换为数值
        var leftB = parseInt(getStyles(canvas).borderLeftWidth);
        var topB = parseInt(getStyles(canvas).borderTopWidth);
        
        function getStyles(obj){//兼容FF,IE10; IE9及以下未测试
            return document.defaultView.getComputedStyle(obj);
        }

        var clickX = (e.clientX - rect.left) - leftB;
        var clickY = (e.clientY - rect.top) - topB ;

        for(var i=circles.length-1; i>=0; i--) {
            var circle = circles[i];
            //使用勾股定理计算这个点与圆心之间的距离
            var distanceFromCenter = Math.sqrt(Math.pow(circle.x - clickX,2) + Math.pow(circle.y - clickY, 2))
            // 判断这个点是否在圆圈中
            if (distanceFromCenter <= circle.radius) {
                previousSelectedCircle = circle;
                //停止搜索
                break;
            }
        }

        //重新绘制canvas
        drawCircles();
        //如果当前鼠标位置有圆圈,还要显示tip
        if(previousSelectedCircle != null){
            drawToolTip(previousSelectedCircle.text , clickX, clickY);
        }
    }

第二步 将原来的绘制方法封装

function drawCircles(){
    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();
    });
   
    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);
}

第三步 实现提示框文字

function drawToolTip(txtLoc, x, y) {
    context.save();
    var padding = 3;
    var font = "18px arial";
    context.font = font;
    context.textBaseline = 'bottom';
    context.fillStyle = '#000';

    //绘制ToolTip背景
    var width = context.measureText(txtLoc).width;
    var height = parseInt(font, 10);
    context.fillRect(x, y-height, width+padding*2, height+padding*2);

    //绘制ToolTip文字
    context.fillStyle = '#fff';
    context.fillText(txtLoc, x+padding, y+padding);

    context.restore();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

似一筷扣肉

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

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

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

打赏作者

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

抵扣说明:

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

余额充值