zoukankan      html  css  js  c++  java
  • 热力图之heatmap

    2021-12-24

    Heatmap.js 是目前应用最广的web动态热图javaScript库。heatmap使用 canvas 进行绘制。

    一、传送门

    Heatmap官网:https://www.patrick-wied.at/static/heatmapjs/

    github下载: https://github.com/pa7/heatmap.js

    二、代码结构

    1、整个js库包裹在一个立即执行的匿名函数里,以避免污染全局命名空间。这也是很多js库的常见写法。
    2、核心对象有三个:Store(数据)、Canvas2dRenderer(绘制工具)、HeatMap(构建器)。
    3、通过global['h337']暴露创建工厂。


    三、热力图渲染原理

    以 heatmap.js v2.0.5 为例子; heatmap使用 canvas 进行绘制。

    Heatmap.js 最重要的4个点: _getPointTemplate, _getColorPalette , _drawAlpha , _colorize

    3.1、点模板 _getPointTemplate,设置单点渲染模板

        点模板对应热力图数据点。它是一个圆点,根据可配置的模糊因子(blurFactor,默认.85),可使圆点带有模糊效果(借助createRadialGradient)。

        主要是调用 canvas 的 createRadialGradient 方法。核心方法是canvas的createRadialGradient方法,每个点设置渲染半径,由渐变因子 blur 确定内圆比例,内圆与外圆的圆周间进行无色的放射渐变,达到中间透明度高,边缘透明度低的效果。这个无色的透明度渐变的圆形即为点的模板。

    var _getPointTemplate = function(radius, blurFactor) {
        var tplCanvas = document.createElement('canvas');
        var tplCtx = tplCanvas.getContext('2d');
        var x = radius;
        var y = radius;
        tplCanvas.width = tplCanvas.height = radius*2;
    
        if (blurFactor == 1) {
          tplCtx.beginPath();
          tplCtx.arc(x, y, radius, 0, 2 * Math.PI, false);
          tplCtx.fillStyle = 'rgba(0,0,0,1)';
          tplCtx.fill();
        } else {
          var gradient = tplCtx.createRadialGradient(x, y, radius*blurFactor, x, y, radius);
          gradient.addColorStop(0, 'rgba(0,0,0,1)');
          gradient.addColorStop(1, 'rgba(0,0,0,0)');
          tplCtx.fillStyle = gradient;
          tplCtx.fillRect(0, 0, 2*radius, 2*radius);
        }
    
        return tplCanvas;
      };

    用 html canvas代码测试效果,代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>_getPointTemplate</title>
      <style>
          /*canvas {border:1px solid black;}*/
      </style>
    </head>
    <body>
    <div class="heatmap">
    </div>
    <script>
      window.onload = function () {
        var container = document.querySelector('.heatmap');
    
        var p1 = _getPointTemplate(40, 0.85);
        //document.body.appendChild(p1);
        container.appendChild(p1);
      }
    
      var _getPointTemplate = function(radius, blurFactor) {
        var tplCanvas = document.createElement('canvas');
        var tplCtx = tplCanvas.getContext('2d');
        var x = radius;
        var y = radius;
        tplCanvas.width = tplCanvas.height = radius*2;
    
        if (blurFactor == 1) {
          tplCtx.beginPath();
          tplCtx.arc(x, y, radius, 0, 2 * Math.PI, false);
          tplCtx.fillStyle = 'rgba(0,0,0,1)';
          tplCtx.fill();
        } else {
          var gradient = tplCtx.createRadialGradient(x, y, radius*blurFactor, x, y, radius);
          gradient.addColorStop(0, 'rgba(0,0,0,1)');
          gradient.addColorStop(1, 'rgba(0,0,0,0)');
          tplCtx.fillStyle = gradient;
          tplCtx.fillRect(0, 0, 2*radius, 2*radius);
        }
        return tplCanvas;
      };
    </script>
    </body>
    </html>
    View Code

    当 radius=50, blurFactor = 0.85 ,测试效果如下:

     当 radius=50, blurFactor = 0.5 ,测试效果如下:

    3.2、线性色谱 _getColorPalette , 构建0到256的调色板

        通过createLinearGradient你可以自主定制自己的热力图色谱(config.gradient)。

     主要是调用 canvas 的 createLinearGradient 方法。核心方法是canvas的createLinearGradient方法

    var _getColorPalette = function(config) {
        var gradientConfig = config.gradient || config.defaultGradient;
        var paletteCanvas = document.createElement('canvas');
        var paletteCtx = paletteCanvas.getContext('2d');
    
        paletteCanvas.width = 256;
        paletteCanvas.height = 1;
    
        var gradient = paletteCtx.createLinearGradient(0, 0, 256, 1);
        for (var key in gradientConfig) {
          gradient.addColorStop(key, gradientConfig[key]);
        }
    
        paletteCtx.fillStyle = gradient;
        paletteCtx.fillRect(0, 0, 256, 1);
    
        return paletteCtx.getImageData(0, 0, 256, 1).data;
      };

    用 html canvas代码测试效果,代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>_getColorPalette</title>
      <style>
          /*canvas {border:1px solid black;}*/
      </style>
    </head>
    <body>
    <div class="heatmap">
    </div>
    <script>
      window.onload = function () {
        var container = document.querySelector('.heatmap');
    
        /*var HeatmapConfig = {
        defaultRadius: 40,
        defaultRenderer: 'canvas2d',
        defaultGradient: { 0.25: "rgb(0,0,255)", 0.55: "rgb(0,255,0)", 0.85: "yellow", 1.0: "rgb(255,0,0)"},
        defaultMaxOpacity: 1,
        defaultMinOpacity: 0,
        defaultBlur: .85,
        defaultXField: 'x',
        defaultYField: 'y',
        defaultValueField: 'value',
        plugins: {}
        };*/
        var config = { defaultGradient: { 0.25: "rgb(0,0,255)", 0.55: "rgb(0,255,0)", 0.85: "yellow", 1.0: "rgb(255,0,0)"} }
    
        var imgData = _getColorPalette(config);
        var c=document.createElement("canvas");
        container.appendChild(c);
        var ctx=c.getContext("2d");
        var img = ctx.getImageData(0, 0, 256, 1)
        //img.data = imgData;
        for (let i = 0; i < img.data.length; i++) {
          img.data[i] = imgData[i];
        }
        ctx.putImageData(img, 0, 0);
      }
    
      var _getColorPalette = function(config) {
        var gradientConfig = config.gradient || config.defaultGradient;
        var paletteCanvas = document.createElement('canvas');
        var paletteCtx = paletteCanvas.getContext('2d');
    
        paletteCanvas.width = 256;
        paletteCanvas.height = 1;
    
        var gradient = paletteCtx.createLinearGradient(0, 0, 256, 1);
        for (var key in gradientConfig) {
          gradient.addColorStop(key, gradientConfig[key]);
        }
    
        paletteCtx.fillStyle = gradient;
        paletteCtx.fillRect(0, 0, 256, 1);
    
        return paletteCtx.getImageData(0, 0, 256, 1).data;
      };
    </script>
    </body>
    </html>
    View Code

    当 var gradientConfig = { 0.25: "rgb(0,0,255)", 0.55: "rgb(0,255,0)", 0.85: "yellow", 1.0: "rgb(255,0,0)"};,测试效果如下:

    3.3、灰度(透明度)叠加 _drawAlpha, 根据模板绘制全部点

         这个热力图的"灵魂"。rgb通道是无法线性叠加呈现效果的,但是透明度是近似线性的。var templateAlpha = (value-min)/(max-min);,根据数据点的比率,对应于透明度的值alpha,我们在canvas上(shadowCtx)绘制一个数据点。它们的透明度是可以叠加的,值越大,越"不透明"。

        主要是调用 canvas 的 drawImage方法。核心方法是canvas的drawImage方法,在每个点的位置按照模板进行绘制,达到重叠部分透明度叠加的效果。

    _drawAlpha: function(data) {
          var min = this._min = data.min;
          var max = this._max = data.max;
          var data = data.data || [];
          var dataLen = data.length;
          // on a point basis?
          var blur = 1 - this._blur;
    
          while(dataLen--) {
    
            var point = data[dataLen];
    
            var x = point.x;
            var y = point.y;
            var radius = point.radius;
            // if value is bigger than max
            // use max as value
            var value = Math.min(point.value, max);
            var rectX = x - radius;
            var rectY = y - radius;
            var shadowCtx = this.shadowCtx;
    
    
    
    
            var tpl;
            if (!this._templates[radius]) {
              this._templates[radius] = tpl = _getPointTemplate(radius, blur);
            } else {
              tpl = this._templates[radius];
            }
            // value from minimum / value range
            // => [0, 1]
            var templateAlpha = (value-min)/(max-min);
            // this fixes #176: small values are not visible because globalAlpha < .01 cannot be read from imageData
            shadowCtx.globalAlpha = templateAlpha < .01 ? .01 : templateAlpha;
    
            shadowCtx.drawImage(tpl, rectX, rectY);
    
            // update renderBoundaries
            if (rectX < this._renderBoundaries[0]) {
                this._renderBoundaries[0] = rectX;
              }
              if (rectY < this._renderBoundaries[1]) {
                this._renderBoundaries[1] = rectY;
              }
              if (rectX + 2*radius > this._renderBoundaries[2]) {
                this._renderBoundaries[2] = rectX + 2*radius;
              }
              if (rectY + 2*radius > this._renderBoundaries[3]) {
                this._renderBoundaries[3] = rectY + 2*radius;
              }
    
          }
        },

     用 html canvas代码测试效果,代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>_drawAlpha</title>
      <style>
          /*canvas {border:1px solid black;}*/
      </style>
    </head>
    <body>
    <div class="heatmap">
    </div>
    <script>
      window.onload = function () {
        var container = document.querySelector('.heatmap');
    
        var shadowCanvas = this.shadowCanvas = document.createElement('canvas');
        this._width = shadowCanvas.width = 900;
        this._height = shadowCanvas.height = 900;
    
        this.shadowCtx = shadowCanvas.getContext('2d');
    
        shadowCanvas.style.cssText = 'position:absolute;left:0;top:0;';
    
        container.style.position = 'relative';
        container.appendChild(shadowCanvas);
    
        var renderBoundaries = this._renderBoundaries = [10000, 10000, 0, 0];
        // this._min
        // this._max
        this._blur = 0.85;
        this._templates = {};
    
        var data = {
          min: 0,
          max: 10,
          // x坐标, y坐标, value值, radius圆半径
          data: [{x: 10, y: 15, value: 5, radius: 40}, {x: 130, y: 170, value: 8, radius: 40}, {x: 200, y: 250, value: 10, radius: 40},
            {x: 300, y: 450, value: 5, radius: 40}, {x: 300, y: 450, value: 5, radius: 40}]
        };
        _drawAlpha(data);
      }
    
      var _getPointTemplate = function(radius, blurFactor) {
        var tplCanvas = document.createElement('canvas');
        var tplCtx = tplCanvas.getContext('2d');
        var x = radius;
        var y = radius;
        tplCanvas.width = tplCanvas.height = radius*2;
    
        if (blurFactor == 1) {
          tplCtx.beginPath();
          tplCtx.arc(x, y, radius, 0, 2 * Math.PI, false);
          tplCtx.fillStyle = 'rgba(0,0,0,1)';
          tplCtx.fill();
        } else {
          var gradient = tplCtx.createRadialGradient(x, y, radius*blurFactor, x, y, radius);
          gradient.addColorStop(0, 'rgba(0,0,0,1)');
          gradient.addColorStop(1, 'rgba(0,0,0,0)');
          tplCtx.fillStyle = gradient;
          tplCtx.fillRect(0, 0, 2*radius, 2*radius);
        }
        return tplCanvas;
      };
    
      var _drawAlpha = function(data) {
        var min = this._min = data.min;
        var max = this._max = data.max;
        var data = data.data || [];
        var dataLen = data.length;
        // on a point basis?
        var blur = 1 - this._blur;
    
        while(dataLen--) {
          var point = data[dataLen];
    
          var x = point.x;
          var y = point.y;
          var radius = point.radius;
          // if value is bigger than max
          // use max as value
          var value = Math.min(point.value, max);
          var rectX = x - radius;
          var rectY = y - radius;
          var shadowCtx = this.shadowCtx;
    
          var tpl;
          if (!this._templates[radius]) {
            this._templates[radius] = tpl = _getPointTemplate(radius, blur);
          } else {
            tpl = this._templates[radius];
          }
          // value from minimum / value range
          // => [0, 1]
          var templateAlpha = (value-min)/(max-min);
          // this fixes #176: small values are not visible because globalAlpha < .01 cannot be read from imageData
          shadowCtx.globalAlpha = templateAlpha < .01 ? .01 : templateAlpha;
    
          shadowCtx.drawImage(tpl, rectX, rectY);
    
          // update renderBoundaries
          if (rectX < this._renderBoundaries[0]) {
            this._renderBoundaries[0] = rectX;
          }
          if (rectY < this._renderBoundaries[1]) {
            this._renderBoundaries[1] = rectY;
          }
          if (rectX + 2*radius > this._renderBoundaries[2]) {
            this._renderBoundaries[2] = rectX + 2*radius;
          }
          if (rectY + 2*radius > this._renderBoundaries[3]) {
            this._renderBoundaries[3] = rectY + 2*radius;
          }
    
        }
      }
    </script>
    </body>
    </html>
    View Code

    测试效果如下:

    3.4、着色 _colorize

         最后,透明度的叠加值(this.shadowCtx.getImageData)映射到线性色谱(palette),取线性色谱中的颜色为canvas上色(putImageData)就得到最终的热力图了。

        主要是调用 canvas 的 putImageData方法。核心方法是canvas的putImageData方法, 对绘制的每个点进行着色,获取绘制的区域中每个像素,根据像素的透明度去调色板中取对应的颜色进行渲染,最后达到热力图的效果。

    _colorize: function() {
          var x = this._renderBoundaries[0];
          var y = this._renderBoundaries[1];
          var width = this._renderBoundaries[2] - x;
          var height = this._renderBoundaries[3] - y;
          var maxWidth = this._width;
          var maxHeight = this._height;
          var opacity = this._opacity;
          var maxOpacity = this._maxOpacity;
          var minOpacity = this._minOpacity;
          var useGradientOpacity = this._useGradientOpacity;
    
          if (x < 0) {
            x = 0;
          }
          if (y < 0) {
            y = 0;
          }
          if (x + width > maxWidth) {
            width = maxWidth - x;
          }
          if (y + height > maxHeight) {
            height = maxHeight - y;
          }
    
          var img = this.shadowCtx.getImageData(x, y, width, height);
          var imgData = img.data;
          var len = imgData.length;
          var palette = this._palette;
    
    
          for (var i = 3; i < len; i+= 4) {
            var alpha = imgData[i];
            var offset = alpha * 4;
    
    
            if (!offset) {
              continue;
            }
    
            var finalAlpha;
            if (opacity > 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] = useGradientOpacity ? palette[offset + 3] : finalAlpha;
    
          }
    
          img.data = imgData;
          this.ctx.putImageData(img, x, y);
    
          this._renderBoundaries = [1000, 1000, 0, 0];
    
        },

    用 html canvas代码测试效果,代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>_colorize</title>
      <style>
          /*canvas {border:1px solid black;}*/
      </style>
    </head>
    <body>
    <div class="heatmap">
    </div>
    <script>
      window.onload = function () {
        var container = document.querySelector('.heatmap');
    
        var shadowCanvas = this.shadowCanvas = document.createElement('canvas');
        var canvas = this.canvas = document.createElement('canvas');
        var renderBoundaries = this._renderBoundaries = [10000, 10000, 0, 0];
    
        canvas.className = 'heatmap-canvas';
    
        this._width = canvas.width = shadowCanvas.width = 900;
        this._height = canvas.height = shadowCanvas.height = 900;
    
        this.shadowCtx = shadowCanvas.getContext('2d');
        this.ctx = canvas.getContext('2d');
    
        canvas.style.cssText = shadowCanvas.style.cssText = 'position:absolute;left:0;top:0;';
    
        container.style.position = 'relative';
        container.appendChild(canvas);
    
        var config = { defaultGradient: { 0.25: "rgb(0,0,255)", 0.55: "rgb(0,255,0)", 0.85: "yellow", 1.0: "rgb(255,0,0)"} }
        this._palette = _getColorPalette(config);
        this._templates = {};
        var opacity = this._opacity = 0.8;
        var maxOpacity = this._maxOpacity = 1;
        var minOpacity = this._minOpacity = 0;
        var useGradientOpacity = this._useGradientOpacity = true;
        // this._min
        // this._max
        this._blur = 0.85;
    
        var data = {
          min: 0,
          max: 10,
          // x坐标, y坐标, value值, radius圆半径
          data: [{x: 10, y: 15, value: 5, radius: 40}, {x: 130, y: 170, value: 8, radius: 40}, {x: 200, y: 250, value: 10, radius: 40},
            {x: 300, y: 450, value: 5, radius: 40}, {x: 300, y: 450, value: 5, radius: 40}]
        };
        _drawAlpha(data);
        _colorize();
      };
    
      var _getColorPalette = function(config) {
        var gradientConfig = config.gradient || config.defaultGradient;
        var paletteCanvas = document.createElement('canvas');
        var paletteCtx = paletteCanvas.getContext('2d');
    
        paletteCanvas.width = 256;
        paletteCanvas.height = 1;
    
        var gradient = paletteCtx.createLinearGradient(0, 0, 256, 1);
        for (var key in gradientConfig) {
          gradient.addColorStop(key, gradientConfig[key]);
        }
    
        paletteCtx.fillStyle = gradient;
        paletteCtx.fillRect(0, 0, 256, 1);
    
        return paletteCtx.getImageData(0, 0, 256, 1).data;
      };
    
      var _getPointTemplate = function(radius, blurFactor) {
        var tplCanvas = document.createElement('canvas');
        var tplCtx = tplCanvas.getContext('2d');
        var x = radius;
        var y = radius;
        tplCanvas.width = tplCanvas.height = radius*2;
    
        if (blurFactor == 1) {
          tplCtx.beginPath();
          tplCtx.arc(x, y, radius, 0, 2 * Math.PI, false);
          tplCtx.fillStyle = 'rgba(0,0,0,1)';
          tplCtx.fill();
        } else {
          var gradient = tplCtx.createRadialGradient(x, y, radius*blurFactor, x, y, radius);
          gradient.addColorStop(0, 'rgba(0,0,0,1)');
          gradient.addColorStop(1, 'rgba(0,0,0,0)');
          tplCtx.fillStyle = gradient;
          tplCtx.fillRect(0, 0, 2*radius, 2*radius);
        }
        return tplCanvas;
      };
    
      var _drawAlpha = function(data) {
        var min = this._min = data.min;
        var max = this._max = data.max;
        var data = data.data || [];
        var dataLen = data.length;
        // on a point basis?
        var blur = 1 - this._blur;
    
        while(dataLen--) {
          var point = data[dataLen];
    
          var x = point.x;
          var y = point.y;
          var radius = point.radius;
          // if value is bigger than max
          // use max as value
          var value = Math.min(point.value, max);
          var rectX = x - radius;
          var rectY = y - radius;
          var shadowCtx = this.shadowCtx;
    
          var tpl;
          if (!this._templates[radius]) {
            this._templates[radius] = tpl = _getPointTemplate(radius, blur);
          } else {
            tpl = this._templates[radius];
          }
          // value from minimum / value range
          // => [0, 1]
          var templateAlpha = (value-min)/(max-min);
          // this fixes #176: small values are not visible because globalAlpha < .01 cannot be read from imageData
          shadowCtx.globalAlpha = templateAlpha < .01 ? .01 : templateAlpha;
    
          shadowCtx.drawImage(tpl, rectX, rectY);
    
          // update renderBoundaries
          if (rectX < this._renderBoundaries[0]) {
            this._renderBoundaries[0] = rectX;
          }
          if (rectY < this._renderBoundaries[1]) {
            this._renderBoundaries[1] = rectY;
          }
          if (rectX + 2*radius > this._renderBoundaries[2]) {
            this._renderBoundaries[2] = rectX + 2*radius;
          }
          if (rectY + 2*radius > this._renderBoundaries[3]) {
            this._renderBoundaries[3] = rectY + 2*radius;
          }
    
        }
      };
    
      var _colorize = function() {
        var x = this._renderBoundaries[0];
        var y = this._renderBoundaries[1];
        var width = this._renderBoundaries[2] - x;
        var height = this._renderBoundaries[3] - y;
        var maxWidth = this._width;
        var maxHeight = this._height;
        var opacity = this._opacity;
        var maxOpacity = this._maxOpacity;
        var minOpacity = this._minOpacity;
        var useGradientOpacity = this._useGradientOpacity;
    
        if (x < 0) {
          x = 0;
        }
        if (y < 0) {
          y = 0;
        }
        if (x + width > maxWidth) {
          width = maxWidth - x;
        }
        if (y + height > maxHeight) {
          height = maxHeight - y;
        }
    
        var img = this.shadowCtx.getImageData(x, y, width, height);
        var imgData = img.data;
        var len = imgData.length;
        var palette = this._palette;
    
    
        for (var i = 3; i < len; i+= 4) {
          var alpha = imgData[i];
          var offset = alpha * 4;
    
    
          if (!offset) {
            continue;
          }
    
          var finalAlpha;
          if (opacity > 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] = useGradientOpacity ? palette[offset + 3] : finalAlpha;
    
        }
    
        img.data = imgData;
        this.ctx.putImageData(img, x, y);
    
        this._renderBoundaries = [1000, 1000, 0, 0];
    
      };
    </script>
    </body>
    </html>
    View Code

    测试效果如下:

     

    当然还有很多其他的方法,这里不一一介绍了。

    四、调用 heatmap.js 生成热力图

    首先引入 heatmap.js 文件:

    官网:https://www.patrick-wied.at/static/heatmapjs/

    github:https://github.com/pa7/heatmap.js

    代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
      <!-- https://www.patrick-wied.at/static/heatmapjs/docs.html -->
      <!--  <link rel="stylesheet" type="text/css" href="style.css">-->
      <!--<script src="../../lib/heatmap.js-master/build/heatmap.min.js"></script>-->
      <script src="https://cdn.bootcdn.net/ajax/libs/heatmap.js/2.0.0/heatmap.min.js"></script>
      <style>
          div {
              width: 100%;
              height: 900px;
              /*border-style:solid;*/
              /*border-color:red;*/
              border:2px solid Orange;
          }
      </style>
    </head>
    <body>
      <div id="heatmap"></div>
      <script type="text/javascript">
        /*
          h337”是heatmap.js注册的全局对象的名字。您可以使用它来创建热图实例
          h337.create(configObject) 返回一个heatmapInstance。
          使用 h337.create 创建热图实例。可以使用 configObject 自定义热图。
          configObject 参数是必需的。
         */
        var heatmap = h337.create({
          // 可能的配置属性:
    
          // container (DOMNode) *必需*
          // A DOM node where the heatmap canvas should be appended (heatmap will adapt to the node's size)
          // 应附加热图画布的 DOM 节点(热图将适应节点的大小)
          container: document.getElementById("heatmap"),
    
          // 背景色
          // backgroundColor (string) *optional*
          // A background color string in form of hexcode, color name, or rgb(a)
          // 十六进制代码、颜色名称或 rgb(a) 形式的背景颜色字符串
          //backgroundColor: "#f3f3f3",
          //backgroundColor: "rgb(240, 240, 240)",
          backgroundColor: "rgba(240, 240, 240, 0.2)",
    
          // gradient (object) *可选*
          // An object that represents the gradient (syntax: number string [0,1] : color string), check out the example
          // 表示渐变的对象(语法:数字字符串[0,1]:颜色字符串),查看示例
          gradient: { 0.25: "rgb(0,0,255)", 0.55: "rgb(0,255,0)", 0.85: "yellow", 1.0: "rgb(255,0,0)"},
    
          // radius (number) *可选*
          // The radius each datapoint will have (if not specified on the datapoint itself)
          // 每个数据点将具有的半径(如果未在数据点本身上指定)
          radius: 20,
    
          // opacity (number) [0,1] *可选* default = .6
          // A global opacity for the whole heatmap. This overrides maxOpacity and minOpacity if set!
          // 整个热图的全局不透明度。如果设置,这将覆盖 maxOpacity 和 minOpacity!
          // opacity: .6,
    
          // maxOpacity (number) [0,1] *可选*
          // The maximal opacity the highest value in the heatmap will have. (will be overridden if opacity set)
          // 热图中最高值的最大不透明度。(如果设置不透明度将被覆盖)
          maxOpacity: 1,
          // minOpacity(number) [0,1] *可选*
          // The minimum opacity the lowest value in the heatmap will have (will be overridden if opacity set)
          // 热图中最低值的最小不透明度(如果设置了不透明度,将被覆盖)
          minOpacity: 0,
    
          // onExtremaChange function callback  函数回调
          // Pass a callback to receive extrema change updates. Useful for DOM legends.
          // 传递回调以接收极值更改更新。对 DOM 图例很有用。
          // onExtremaChange
    
          // blur (number) [0,1] *可选* default = 0.85
          //
          // 将应用于所有数据点的模糊因子。模糊系数越高,渐变就越平滑
    
    
          // xField (string) *可选* default = "x"
          //
          // 数据点中 x 坐标的属性名称
          xField: "x",
    
          // yField (string) *optional* default = "y"
          //
          // 数据点中 y 坐标的属性名称
          yField: "y",
    
          // valueField (string) *optional* default = "value"
          //
          // 数据点中 y 坐标的属性名称
          valueField: "value"
        });
    
        heatmap.setData({
          min: 0,
          max: 10,
          data: [{x: 10, y: 15, value: 5, radius: 40}, {x: 130, y: 170, value: 8, radius: 40}, {x: 200, y: 250, value: 10, radius: 40},
            {x: 300, y: 450, value: 5, radius: 40}, {x: 300, y: 450, value: 5, radius: 40}]
          //data: [{ x: 50, y: 75, value: 5, radius: 40}, {x: 200, y: 350, value: 3, radius: 10}]
        });
      </script>
    </body>
    </html>

    结果如下:

    参考: 

    heatmap.js(热力图)源码解读

    热点图heatMap.js V2.0 研究笔记

  • 相关阅读:
    LinuxShell脚本攻略--第八章 当个好管家
    LinuxShell脚本攻略--第六章 B计划
    LinuxShell脚本攻略--第三章 以文件之名
    LinuxShell脚本攻略--第二章 命令之乐
    LinuxShell脚本攻略--第一章 小试牛刀
    TCP/IP 与OSI结构图
    网络号和主机号的计算
    IP地址分类及私网IP
    转:Cache相关
    原码 反码 补码 移码
  • 原文地址:https://www.cnblogs.com/zhangchao0515/p/15726301.html
Copyright © 2011-2022 走看看