用户体验

基于Canvas的热力图绘制方法

上面的代码将会呈现:

image

显而易见,这并不是热力图,但是可以精确反映每个点的分布密度,红色表示在该区域的点数据较多,浅,蓝色表示密度小。那么如何改进?

使用径向渐变代替圆点的绘制,用以表示每一个点向周围的点的辐射,渐变色的叠加可以展现梯度变换的效果。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
var aXY = [[x1, y1], [x2, y2], [x3, y3], [x4, y4]...];
var context = canvas.getContext('2d');
for (var i = 0, len = aXY.length; i < len; i++) {
    var x = aXY[i][0], y = aXY[i][1];
    //绘制径向渐变
    var radgrad = this.context.createRadialGradient(x, y, 1, x, y, 8);
    //锚点
    radgrad.addColorStop( 0, 'rgba(255,30,0,1)');
    //锚点
    radgrad.addColorStop( 1, 'rgba(255,30,0,0)');
    context.fillStyle = radgrad;
    context.fillRect( x - 8, y - 8, 16, 16);
}

效果如下:

image

方案度量:这是比较简单的实现方案,稍微麻烦的地方在于根据alpha值计算红蓝绿值,使得alpha高的地方显示红色,alpha低的显示蓝色, 中间部分显示黄/绿色(考虑到效率与简单性,使用了简单的三角函数,如果需要更为精确的色相渐变,可以使用幂次变换)。同时这个方案的缺点也十分明显:在 点数据量低的时候效率很高,但是点数据超过10000之后就会有明显的时间延迟>3s,原因在于循环绘制渐变色会消耗资源。其次该方案的性能也会取 决于画布的大小。画布大的情况,比如画布尺寸为1200*3000,对其取位数据的时候,将会循环360万次,同时进行3*360万sin运算~~对于客 户端性能是个问题。

方法二

思路:对所有点数据进行计算,得出每个点的密度值,然后依据密度值由低到高,绘制点数据。

代码:

希望看到您的想法,请您发表评论x