HTML5 - 有效地绘制巨大的2D热图

时间:2015-10-16 02:29:38

标签: javascript html5 canvas plot heatmap

我想快速生成约300万点的2D热图。我目前使用vanilla javascript用单个线程写入<canvas>的尝试太慢了(约1-2秒)。如何轻松,高效地完成这项工作?

我愿意使用像THREE.js或pixi.js这样的现有库,如果能够快速完成的话。

详情

所以步骤是:

  1. 在列表中找到最小/最大值
  2. 对于每个点:映射到一种颜色(基于上面的最小值/最大值)并确定x / y位置(只是每个点的增量)
  3. 写入页面,例如<canvas>元素
  4. 我的缓慢解决方案jsfiddle及以下

    <!DOCTYPE html>
    <html>
    <body>
    <canvas id="myCanvas" width="1500px" height="1500px" style="border:1px solid #d3d3d3;" ></canvas>
    
    <script>
    function getInterpolatedColor(colorscale, min, max, val) {
      var maxIndex = colorscale.length - 1,
          colorIncrement = (max - min) / maxIndex;
    
      if (colorIncrement === 0) {
        return 255;
      }
    
      var baseColor = Math.floor((val - min) / colorIncrement),
          percentage = (val - (min + colorIncrement * baseColor)) / colorIncrement;
      if (percentage > 1.0) {
        percentage = 0.0;
        baseColor = baseColor + 1;
      }
    
      var color = 255;
      if ((baseColor >= 0) && (baseColor < (maxIndex))) {
        color = colorscale[baseColor] +
                ((colorscale[baseColor + 1] - colorscale[baseColor]) * percentage);
      } else {
        color = (baseColor < 0) ? colorscale[0] : colorscale[maxIndex];
      }
    
      return color;
    }
    
    
    var canv = document.getElementById('myCanvas'),
        xSize = 1500,
        ySize = 1500,
        count = xSize * ySize,
        values = new Array(count),
        min = 101,
        max = -1;
    
    for (var i = 0; i < count; ++i) {
      var val = Math.random() * 100;
      values[i] = val;
      if(val>max) max = val;
      if(val<min) min = val;
    }
    
    // #FF0000 #FF8000 #FFFF00 #00FF00 #0000FF #4C007F
    var rgbScale = {
      "red" : [255, 255, 255, 0, 0, 76],
      "green" : [0, 128, 255, 255, 0, 0],
      "blue" : [0, 0, 0, 0, 255, 127]
    };
    
    var ctx = canv.getContext("2d"),
        id = ctx.getImageData(0, 0, xSize, ySize),
        data = id.data;
    for (var xIndex = 0; xIndex < xSize; ++xIndex) {
      for (var yIndex = 0; yIndex < ySize; ++yIndex) {
        var index = ((xIndex * ySize) + yIndex),
            canvasId = index*4,
            val = values[index] * 1;
    
        var red = Math.floor(getInterpolatedColor(rgbScale["red"], min, max, val));
        red = (red > 255) ? 255 : red;
    
        var green = Math.floor(getInterpolatedColor(rgbScale["green"], min, max, val));
        green = (green > 255) ? 255 : green;
    
        var blue = Math.floor(getInterpolatedColor(rgbScale["blue"], min, max, val));
        blue = (blue > 255) ? 255 : blue;
    
        data[canvasId + 0] = red;
        data[canvasId + 1] = green;
        data[canvasId + 2] = blue;
        data[canvasId + 3] = 255;
      }
    }
    
    ctx.putImageData(id, 0, 0);
    
    </script>
    </body>
    </html>
    

0 个答案:

没有答案