绘制大量线条时的HTML画布性能

F.X*_*.X. 12 html javascript html5 canvas

我正在编写一个显示很多的应用程序,我的意思是,在HTML5画布上有很多2D路径(由数百个,数千个小段组成).通常,几百万点.这些点从服务器下载到二进制文件中ArrayBuffer.

我可能不会在现实世界中使用那么多点,但我对如何提高性能感兴趣.如果你愿意,可以称之为好奇心;)

无论如何,我测试了以下解决方案:

  1. 使用gl.LINESgl.LINE_STRIP使用WebGL,并计算GPU上着色器中的所有内容.目前最快的,可以显示多达10M的细分,而不会在我的Macbook Air上退缩.但是如果你想避免在JavaScript中处理事情,那么对二进制格式有非常严格的限制.

  2. 使用Canvas2D,在一次stroke()调用中绘制一条包含所有段的巨大路径.当我超过100k点时,页面会在画布更新前冻结几秒钟.所以,不在这里工作.

  3. 使用Canvas2D,但使用自己的stroke()调用绘制每个路径.尽管其他人一直在互联网上说,这比在一次调用中绘制所有内容要快得多,但仍然比WebGL慢很多.当我达到约500k段时,事情开始变得糟糕.

两个Canvas2D解决方案需要循环遍历JavaScript中所有路径的所有点,因此这非常慢.您是否知道可以提高JavaScript在ArrayBuffer中的迭代速度或一般处理速度的方法?

但是,奇怪的是,在所有画布绘制调用完成后,屏幕不会立即更新.当我开始达到性能限制时,绘制调用结束和画布更新之间会有明显的延迟.你知道它来自哪里,有没有办法减少它?

F.X*_*.X. 7

首先,WebGL是一个很好的炒作理念,但解码和显示二进制数据所需的处理量在着色器中不起作用,因此我将其排除在外.

这是我遇到的主要瓶颈.其中一些在一般编程中很常见,但记住它们是个好主意:

  • 这是最好用多个小for
  • 尽可能在最高级别创建变量和闭包,不要在for循环中创建它们
  • 以块的形式呈现数据,并setTimeout在几毫秒后用于计划下一个块:这样,用户仍然可以使用UI
  • JavaScript对象和数组快速而便宜,使用它们.最好从开始到结束按顺序读/写它们.
  • 如果不在数组中按顺序写入数据,请使用对象 (因为非顺序读写对于对象来说是便宜的)并将索引推送到索引数组中.我使用SortedList实现来保持索引排序,我在这里找到.开销很小(大约是渲染时间的10-20%),最后它非常值得.

这就是我记得的一切.如果我找到别的东西,我会更新这个答案!