heatmap原理简介

来源:互联网 发布:宜昌学历网络教育 编辑:程序博客网 时间:2024/05/22 09:51

昨天twaver mono-design客户发来邮件想控制温度云图中温度点的渐变的颜色半径(红色太多,其他渐变色太少),今天早上研究了下heatmap.js里面的代码,找到控制的办法,能解决客户的需求,也学到了一些妙招,跟大家分享一下

之前有简单了解过heatmap有一个调色板,每个点的对应颜色值就是从这个调色板上拿出来的,就先看了生成调色板的代码

设置调色板上的颜色

var gradient = {

       0.25 :"rgb(0,0,255)",

       0.5 :"rgb(0,255,255)",

       0.75 :"rgb(0,255,0)",

       1.0 :"rgb(255,0,0)"

}

setGradient(gradient);

 

然后根据设置的颜色在canvas上画了一个宽度为1,高度为256的线性渐变,这样就生成了一个有256种颜色的调色板了,并将调色板的数据缓存起来

function generalColorPalette() {

       var canvas =document.createElement("canvas"), gradient =this.get("gradient"), ctx, grad;

       canvas.width ="1";

       canvas.height ="256";

       ctx =canvas.getContext("2d");

       grad =ctx.createLinearGradient(0, 0, 1, 256);

       for (var x ingradient) {

              grad.addColorStop(x,gradient[x]);

       }

       ctx.fillStyle =grad;

       ctx.fillRect(0,0, 1, 256);

       this.set("gradientdata",ctx.getImageData(0, 0, 1, 256).data);

}

 

调色板弄清楚后就想着,heatmap是如何绘制添加给它的点的,于是跟踪一遍,heatmap会缓存场景中的最大值,每次添加点的时候,如果最大值改变就会将所有的点重新绘制一遍;如果最大值不变,则仅绘制新添加的点

 

heatmap绘制点用到一个妙招,就是利用阴影,它在可视区域只绘制了一个圆阴影效果,而圆本身的位置在可视区域之外

ctx.shadowColor = ('rgba(0,0,0,' + ((count) ? (count /this._max) : '0.1') + ')');

var temp = 15000;

ctx.shadowOffsetX = temp;

ctx.shadowOffsetY = temp;

ctx.shadowBlur = 15;

ctx.beginPath();

ctx.arc(x - temp, y - temp, radius, 0, Math.PI * 2, true);

ctx.closePath();

ctx.fill();

而测试shadowBlur阴影的模糊值越大,红色区域就越小,这个值是常量15,那就把这个值提供一个设置方法,就解决了客户的需求

 

但是还是有不清楚的地方,如阴影应该是黑色的,我们实际看到的颜色是有渐变的,而且最开始的调色板也还没有使用呢,而且阴影显示的颜色就是调色板上面的颜色

继续跟踪代码发现,在后面有按照像素点重新着色的方法

var palette = this.get("gradientdata");

image = actx.getImageData(left, top, right - left, bottom -top);

imageData = image.data;

length = imageData.length;

for (var i = 3; i < length; i += 4) {

       alpha =imageData[i], offset = alpha * 4;

       if (!offset)

              continue;

       finalAlpha =(alpha < opacity) ? alpha : opacity;

       imageData[i - 3]= palette[offset];

       imageData[i - 2]= palette[offset + 1];

       imageData[i - 1]= palette[offset + 2];

 

       imageData[i] =finalAlpha;

}

image.data = imageData;

getImageData返回的数组中,每4个元素为一个颜色,4个元素分别为R - 红色 (0-255)、G - 绿色 (0-255)、B - 蓝色 (0-255)、A - alpha 通道 (0-255; 0 是透明的,255 是完全可见的)

获取每个像素颜色的alpha,并获取在调色板(palette)上对应的颜色,并赋给自己。因为html5的阴影效果alpha是递减的,所以在获取颜色的时候,就能得到一个平滑的渐变效果

 

到了这里,有人可能会问为什么要用这种方法呢,canvas上也有径向渐变?

1、渐变的效果见下图,前者是阴影生成效果,后者是径向渐变


前者是通过透明度去对应拿颜色的,因为阴影效果的透明度就是递减的,是canvas本身的处理,效果应该是最理想的,阴影效果可以设置模糊度,所以1中的前者的效果比较舒服

阴影效果见下图,第二张图是值修改了1/6的像素点效果



2、融合效果


当两个点的叠加时,利用透明度的变化去取值效果也更好,而且最关键的一点,这些效果是给温度云图使用的,要有场景的效果,即整个场景里面的温度是相互影响的,每个点的温度值对其他点的颜色也有影响的,是如何影响的呢?在上面的代码中能看到

ctx.shadowColor = ('rgba(0,0,0,' + ((count) ? (count /this._max) : '0.1') + ')');

当前点的值/场景中最大值,获取权重,来设置透明度的,权重得以用颜色体现出来

 


0 0
原创粉丝点击