关于热力图的二三事

首先我们需要了解的是什么是热力图。
以特殊高亮的形式显示访客热衷的页面区域和访客所在的地理区域的图示。 热力图可以显示不可点击区域发生的事情。

一、 原理

  1. 数据点绘制(位置+权重)权重越大,点显示越显著。所以点设置成一个从中心向外的灰度渐变的圆;
  2. 数据点相互叠加,利用灰度叠加原理,计算每个像素点数据交叉叠加后的灰度值;圆半径属性,主要表示数据点的影响范围,是一个缓冲作用;为了便于处理,所有圆半径视为一样,只从权重不同来分辨。
  3. 根据灰度值在彩色色带中进行颜色映射,对图像进行着色,从而得到热力图。

二、实现

  1. 单个点绘制.
        function pointTmp(point,radius){
            var tplCanvas = document.createElement('canvas');
            var tplCtx = tplCanvas.getContext('2d');
            var x = radius;
            var y = radius;
            tplCanvas.width =  radius*2;
            tplCanvas.height = radius*2;    
            tplCtx.beginPath();
                        //添加径向/圆渐变
            tplCtx.arc(x,y,radius,0, 2 * Math.PI,false);
            var gradient = tplCtx.createRadialGradient(x,y,0,x,y,radius)
            gradient.addColorStop(0,'rgba(0,0,0,1)');
            gradient.addColorStop(1,'rgba(0,0,0,0)');
            tplCtx.fillStyle = gradient;
            tplCtx.closePath();
            tplCtx.fill();
            return tplCanvas
        }
单点图.png
  1. 创建多个点。
        for(i = 0; i < 500;i++){
            var point = {};
            point.x = Math.floor(Math.random()*(1000-1)+200);
            point.y = Math.floor(Math.random()*(500-1)+100);
            point.value = Math.floor(Math.random()*(100-1)+1);
            drawPoint(point,defaultRadius);
        }
          drawPanel();
        function drawPoint(point,radius){
            var x = radius;
            var y = radius;
            var tmp = pointTmp(point,radius);
            var rectX = point.x - radius;
            var rectY = point.y - radius;
            

            var alpha = (point.value - minCount)/(maxCount - minCount);
            alpha = alpha > 1 ? 1:alpha;
            console.log(alpha)
            shadowCtx.globalAlpha = alpha;
            shadowCtx.drawImage(tmp,rectX,rectY);

             if (rectX < renderBoundaries[0]) {
                renderBoundaries[0] = rectX;
              } 
              if (rectY < renderBoundaries[1]) {
                renderBoundaries[1] = rectY;
              }
              if (rectX + 2*radius > renderBoundaries[2]) {
                renderBoundaries[2] = rectX + 2*radius;
              }
              if (rectY + 2*radius > renderBoundaries[3]) {
                renderBoundaries[3] = rectY + 2*radius;
              }
    
        }
        function drawPanel(){
            var width = renderBoundaries[2] - renderBoundaries[0];
            var height = renderBoundaries[3] - renderBoundaries[1];
            var x = renderBoundaries[0];
            var y = renderBoundaries[1];
            var img = shadowCtx.getImageData(x, y, width, height);
            ctx.putImageData(img,x,y)

        }

多个点图.png
  1. 创建色带
        //创建色带
        function getColorPalette(){
            var paletteCanvas = document.createElement('canvas');
            var paletteCtx = paletteCanvas.getContext('2d');
            var defaultGradient = { 0.25: "rgb(0,0,255)",
                                    0.55: "rgb(0,255,255)",
                                    0.65: "rgb(0,255,0)", 
                                    0.95: "yellow", 
                                    1.0: "rgb(255,0,0)"} ;
            
            paletteCanvas.width = 256;
            paletteCanvas.height = 10;
    
            var gradient = paletteCtx.createLinearGradient(0,0,256,1);

            for(var key in defaultGradient){
                gradient.addColorStop(key,defaultGradient[key]);
            }
            
            paletteCtx.fillStyle = gradient;
            paletteCtx.fillRect(0,0,256,10);
            return paletteCanvas;
        }
色带图.png
  1. 利用色带着色
        function colorizeCtx(){
            var width = renderBoundaries[2] - renderBoundaries[0];
            var height = renderBoundaries[3] - renderBoundaries[1];
            var x = renderBoundaries[0];
            var y = renderBoundaries[1];
            
            var img = shadowCtx.getImageData(x, y, width, height);
            var imgData = img.data;
            var len = imgData.length;
            var opacity = 0;
            var maxOpacity = 255;
            var minOpacity  = 0;
            var bln = false;

              for(var i = 3;i 0) {
                  finalAlpha = opacity;
                } else {
                  if (alpha < maxOpacity) {
                    if (alpha < minOpacity) {
                      finalAlpha = minOpacity;
                    } else {
                      finalAlpha = alpha;
                    }
                  } else {
                    finalAlpha = maxOpacity;
                  }
                }

                imgData[i-3] = palette[offset];
                imgData[i-2] = palette[offset + 1];
                imgData[i-1] = palette[offset + 2];
                imgData[i] = bln ? palette[offset + 3] : finalAlpha;
              }
            
            img.data = imgData;
            ctx.putImageData(img,x,y)
        }
最终效果图.png

至此热力图基本绘制初步完成。

具体代码可在此下载:下载地址

欢迎交流共同进步

主要参考资料:

HTML 5 canvas相关知识 Canvas参考手册
热力图文件 heatMap.js

你可能感兴趣的:(关于热力图的二三事)