canvas实现温度热力图、温度分布图。现在市场上的热力图都是根据同一点的数量来表示当前点的热度。随着物联网温度传感器的使用,越来越多的业务开始监控一个平面或者一个区域的温度,然而这种监控的可视化是现在的echarts也没有提供很好的表现形式。我就自己研究了一下,简单实现一下,温度分布图。
本专题将持续更新:
基于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();
}