Javascript HTML5画布重画周期性能优化

Javascript HTML5画布重画周期性能优化,javascript,optimization,paperjs,Javascript,Optimization,Paperjs,我们正在构建一个在浏览器中运行的CAD应用程序 C.A.D代表 Illustrator、CorelDraw、AutoCAD等都是CAD应用程序的一些示例 它基于一个非常整洁的画布库,允许您以编程方式操作向量 问题 目前我面临的主要问题是重新绘制循环性能 重画算法是“愚蠢的”(就提高性能的巧妙技巧而言),因此效率低下且渲染速度慢-场景图项目取决于逐渐较慢的重画周期 随着绘制点的累积,每个重绘周期都会变得越来越慢 重画方案非常简单: 清理整个区域 从场景图中获取所有项目 重新绘制所有项目

我们正在构建一个在浏览器中运行的CAD应用程序

  • C.A.D代表
  • Illustrator、CorelDraw、AutoCAD等都是CAD应用程序的一些示例
它基于一个非常整洁的画布库,允许您以编程方式操作向量


问题 目前我面临的主要问题是重新绘制循环性能

重画算法是“愚蠢的”(就提高性能的巧妙技巧而言),因此效率低下且渲染速度慢-场景图项目取决于逐渐较慢的重画周期

随着绘制点的累积,每个重绘周期都会变得越来越慢

重画方案非常简单:

  • 清理整个区域
  • 从场景图中获取所有项目
  • 重新绘制所有项目
问题 在这种情况下是否有渲染优化的课堂示例?假设我不想实现脏矩形算法(仅绘制已更改的区域)

编辑:我已经尝试过手动现场光栅化,效果非常好,我在下面发布了一个答案。

有用的工具 可能会有帮助,但它可能不是最适合你的

它使您能够防止paper.js在每一帧重新绘制所有内容(使用
paper.view.persistence=1;

通过这种方式,您可以更好地控制要清除的内容和应该重新绘制的内容:例如,当您移动形状时,可以清除它所在的区域(例如,使用本机canvas drawRect), 并在移动后进行更新(使用
path.needsUpdate();

缺点 当形状相交时,问题就出现了。如果要修改与另一个形状相交的形状,则必须同时更新这两个形状。如果第二个形状与第三个形状相交,则情况相同,依此类推

因此,您需要一个递归函数,不难编码,但如果有许多复杂形状相交,那么它的成本可能会很高,因此在这种情况下,您可能无法获得性能

(更新)位图缓存 正如中所建议的,位图缓存是一个非常好的解决方案

每个形状一块帆布 另一种方法是在单独的画布上绘制每个形状(作为层)。通过这种方式,您可以独立地自由清除和重新绘制每个形状。可以分离未更改视图的onFrame事件(除用户正在工作的画布外的所有画布)。这应该更容易,但它会导致其他小问题,例如共享相同的项目视图参数(在缩放的情况下),并且对于许多形状(这意味着许多画布)来说可能代价高昂

静态和动态画布
一个(可能)更好的方法是只有两个画布,一个用于静态形状,一个用于活动形状。静态形状画布将包含所有形状(正在编辑的形状除外),并将在用户开始和停止编辑活动形状时重新绘制。当用户开始编辑一个形状时,它将从静态画布转移到动态画布,当用户停止编辑时,它将从静态画布转移到动态画布。

这可以通过类似于的过程/技术中的光栅化来完成

高节点数场景图的问题是渲染它们会导致渲染引擎发出呻吟声。浏览器必须遍历它们的节点并在画布上渲染它们的像素

因此,这里有一个很好的解决方案:


1.渲染位图,但保持下面的原始形状处于隐藏状态 解决方案是用图像替换矢量,将其光栅化- 仅在渲染时,但仍将原始形状保持在其下方 图像复制,仅当处于非活动状态(当前未处于活动状态)时处于隐藏状态 操纵的)

单击图像-我们将其删除并切换原始形状的可见性。通过这种方式,非活动形状被渲染为图像,活动形状从位图表示中释放,并作为向量,可以自由地进行操作。当它们不处于活动状态时,它们只是坐在那里,上面放着光栅副本,不受攻击

这允许引擎保留形状的矢量表示,但避免将其渲染为矢量-相反,看起来与形状相似的图像将分层在形状之上

1000个路径命令基本上由单个图像替换(但仅在渲染时),原始路径实际上作为对象存在于场景图中,或者使用任何类型的DOM

2.成组光栅化 诀窍是成组执行光栅化-将10-15个形状组合在一起,并将它们作为单个图像进行光栅化。这将使光栅计数保持较低。点击一个图片-我们可以释放整个组或者仅仅是点击的项目

3.在组上附加单击处理程序,以在重新激活时恢复向量副本
当光栅化一个组时,我们只需在其上附加一个
click
处理程序,所以当单击时,我们可以使用向量切换位图。命中测试时,图像的行为与向量不同-图像本质上是
正方形
,无法进行非对称命中测试。当一个向量认为它的边在它的路径边界上时,一个图像认为它的边界就是它的整个边界框。解决方案是单击图像以实际点击图像下方的向量路径测试点击点-如果返回true,则执行发布。

为什么您认为paper.js是高度优化的,甚至是优化的?绝大多数库的运行时性能都非常差:好的性能需要大量的代码,这与尽可能小的大小相冲突。我只是相信创作者说的。再加上它是面向动画的,我得出结论,他们说的是真的。即使不是,在我的应用程序所需的功能方面,也没有一个库可以与我竞争。这是API让我至少涵盖了80%的内容