【问题标题】:Plotting a very large number of points on HTML5 canvas with JavaScript使用 JavaScript 在 HTML5 画布上绘制大量点
【发布时间】:2015-12-08 00:26:40
【问题描述】:

我正在尝试在 HTML5 画布上绘制大量 (60k) 个 (x, y) 点,并在 Chrome 和 Firefox 中使用 D3.js 模拟流数据点,发现浏览器在大约 10 分钟后冻结并崩溃秒。

我正在生成具有如下随机值的数据集:

var data = d3.range(60000).map(function() { return Math.random() * 500; });

将数据的生成分成几个部分会有所帮助吗?我觉得这可能是由于尝试一次存储如此大的数据集造成的。

有什么方法可以防止这种情况发生吗?例如将较小的部分绘制并保存为平铺图像?

添加代码:

var margin = {top: 20, right: 20, bottom: 20, left: 40},
    w = 100 - margin.left - margin.right,
    h = 100 - margin.top - margin.bottom;

    var canvas = d3.select("canvas")
      .node();

    var context = canvas.getContext('2d');

    var scale = d3.scale.linear()
    . range([0,w])
    .domain([0,h]);


    data = d3.range(60000).map(function(){return Math.random()*500});
    data.forEach(function(d,i) {
      context.strokeStyle="red";
      context.lineWidth="1";
      context.lineTo(scale(++k),scale(d));
      context.stroke();
    });

【问题讨论】:

  • 我不知道您想要实现哪种图表或绘图,但您是否考虑过使用 WebGL 来利用 GPU?
  • 问题不大,你是用d3在画布上还是svg上做的。
  • 我正在使用画布。
  • 我什至有这个失败: for (j = 0; j
  • 我担心输入 60K (x,y) 坐标只会导致同样的崩溃。

标签: javascript memory d3.js


【解决方案1】:

由于您在评论部分提出了一个完全不同的问题,所以我想换一个答案。

内联注释和工作代码。

var margin = {top: 20, right: 20, bottom: 20, left: 40},
    w = 100 - margin.left - margin.right,
    h = 100 - margin.top - margin.bottom;

    var canvas = d3.select("canvas")
      .node();

    var context = canvas.getContext('2d');

 var data = d3.range(11).map(function(){return Math.random()*10})
    var x = d3.scale.linear().domain([0, 10]).range([0, 700]);
    var y = d3.scale.linear().domain([0, 10]).range([10, 290]);
    var line = d3.svg.line()
      .interpolate("cardinal")
      .x(function(d,i) {console.log(x(i));return x(i);})
      .y(function(d) {return y(d);})
    //making a dummy SVG
    var path = d3.select("body").append("svg").append("path")
      .attr("d", line(data))
      .attr("stroke", "steelblue")
      .attr("stroke-width", "2")
      .attr("fill", "none").remove();
   d3.select("body svg").remove();

    //going from 0 to the paths total length and storing all the points
    var points = [];
    for(var i =0; i < path.node().getTotalLength(); i++){
        points.push(path.node().getPointAtLength(i));//store point @ that length
    }
    var id = window.setInterval(function(){
      console.log("Doing")
      var point = points.shift();//take each point
      context.strokeStyle="red";
      context.lineWidth="1";
      context.lineTo(point.x,point.y);
      context.stroke();
      if(points.length <= 0){
        console.log("Finished")
        window.clearInterval(id);//clear the interval since the drawing is complete
      }
    }, 10)
    
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<!DOCTYPE html>
<html>

  <head>
    <link rel="stylesheet" href="style.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.10/d3.js"></script>
    
  </head>

  <body>
    <canvas id="myCanvas" width="500" height="500" style="border:1px solid #000000;">
</canvas>
  <script src="script.js"></script>
  </body>

</html>

Plunker 上的工作代码。

【讨论】:

    【解决方案2】:

    问题出在这里:

    data.forEach(function(d,i) {
          context.strokeStyle="red";
          context.lineWidth="1";
          context.lineTo(scale(++k),scale(d));
          context.stroke();//this should be out of the for loop you should be doing it once not everytime
        });
    

    类似这样的:

    data.forEach(function(d,i) {
      context.strokeStyle="red";
      context.lineWidth="1";
      var j = scale(d);
      var m = scale(d++);
      context.lineTo(j,m);
    });
    context.stroke();
    

    工作代码here

    希望这会有所帮助!

    【讨论】:

    • Cyril 是否存在可以动画为路径的动画,在画布上而不是在 SVG 中,因此它看起来类似于 bl.ocks.org/duopixel/4063326
    • Bob,如果我在上面的答案中回答了您的问题,请将其标记为已接受。对于您的第二个查询,请提出另一个 SO 问题,我可以在那里复制我的其他答案。以便对有类似问题的其他人有所帮助。
    猜你喜欢
    • 1970-01-01
    • 2011-12-10
    • 1970-01-01
    • 1970-01-01
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 2019-04-12
    • 2013-08-06
    相关资源
    最近更新 更多