原文地址点这里英文链接
1、fabric对象缓存如何执行的?
如果存在对象缓存,你在canvas画布上绘制的对象也会在另一个小一点的canvas以外的地方预绘制,两个canvas的像素尺寸是一样的。在执行render()方法期间,预绘制的对象会采用drawImage(绘制图片的)操作被复制到主画布上。也就是,当你drag,rotate,skew,scale对象的时候是不会在canvas上重新绘制的,而仅仅是将该对象的副本缓存图片绘制到canvas上。
2、如何自设置fabric对象缓存?
-
objectCaching
是主要的属性,对于浏览器默认设置为true, 对于Node默认是false,表示对对象开启了对象缓存。 -
statefullCache
该属性规定:如果是时候重新绘制缓存副本或者开发手动使缓存副本无效,fabric
是否应自动清除。此属性默认为false。稍后会详细介绍。 -
noScaleCache
默认为true,不允许在scale操作的时候再创建缓存。可以启用它以避免大缩放的模糊效果。 -
cacheProperties
每次调用Object.set(key,value)时,都会在此属性数组中搜索key。如果发现它将对象标记为需要重新渲染,StatefullCache设置为true,而不是在每次渲染时将所有键与旧值的副本进行显示的比较。 -
dirty
是一个简单的标志,在下一个渲染方法中强制缓存重新渲染,并在缓存重新生成后自动设置为false。 -
fabric.perfLimitSizeTotal
生成缓存画布的像素区域的最大大小 -
fabric.maxCacheSideLimit
缓存画布最大边的像素的最大大小。 (比IE大5000) -
fabric.minCacheSideLimit
缓存画布最小边的像素的最小大小。 (小于256的数字可以禁用gpu合成。待验证)
以下是缓存的canvas对象大于绘制的canvas对象的例子(默认最小大小是256x256)
图片在原文中查看
默认值最大大小缓存画布示例(2M 像素)。滚动查看。
图片在原文中查看
3、有多少性能提升,有什么问题吗?
取决于你绘制的对象的样子。
如果你仅仅导入一些圆、矩形或者其他简单的对象,那么你不大会体验到这种性能上的差别。
您是否导入并显示大型复杂的svgs?那么你将从难以操作转移到平滑操作。我应该注意哪些细节?那么你可能不喜欢noScaleCache
功能,这就是为什么有一个标志来禁用它。
4、我当前项目的兼容性问题怎么样?我应该更新吗?我可以禁用缓存吗?
我会说是的,更新到1.7.0版本,检查一切是否正常。如果对问题跟踪器没有报告任何视觉问题,您仍然可以在任何地方完全禁用对象缓存:
fabric.Object.prototype.objectCaching = false;
在原文中体验使用了对象缓存和没有使用对象缓存的差别(注意拖动速度)
5、什么时候使用新版本更新缓存?
Fabric
具有硬编码触发器,用于在内置函数期间更新缓存,这期间开发人员很难插入代码。这些情况是: 缩放(scaling)、输入文字(typing text)、画布全局缩放(canvas global zoom)
在所有其他情况下,开发人员更改对象的某些属性以检测触发更改,因此他可以通过dirty
属性将对象设置为脏操作。这将使用对象的set
方法为您执行此操作。比如调用object.set('fill', 'red')
不需要其他操作。
如果因为一些其他的原因没有使用set
方法(例如,在设置某些属性的文本对象的情况下触发开销较大的功能),你可以使用标题2中的标签属性。
存在别的方法可以让fabric
在渲染期间检查属性的更改。但我决定放弃它,因为这在大多数时候开销并不大,但是在复杂的情况下(如喷刷或1000+的svg路径)开销太大。
当设置一个canvas对象的属性的时候,该属性会被检测。如果该属性在cacheProperties
数组中,该对象和该对象所在的组都将设置为脏操作(dirty = true), 否则只有该对象所在的组设置为脏操作。
6、Fabric如何使用自定义属性检查自定义子类中的更改?
我认为自定义子类是fabric
中最强大的功能,而对象缓存是在考虑到这一点的基础上构建的,因此定义了cacheProperties
这个数组来包含这些属性列表,当statefullCache
设置为true(默认是false)的时候,在渲染的时候会一一检测这些属性列表。
这个数组如下:
cacheProperties: (
'fill stroke strokeWidth strokeDashArray width height' +
' strokeLineCap strokeLineJoin strokeMiterLimit fillRule backgroundColor'
).split(' '),
在不同的子类中会获取到更多的属性,比如正方形会获取rx以及ry属性等等。以递归方式检查这些属性,这意味着在检测到的每个更改中都会保存属性的副本,并在下一次渲染时进行深入比较。通常,需要深度检查的属性是gradients
(渐变),patterns
(模式),path array
(路径数组)以及strokeDash
属性。如果您的应用程序根本不使用某些属性,则可以从cacheProperties数组中删除它们使检测更快,或者您可以添加影响渲染的自定义属性以检测它们。
7、陷阱
有一个隐藏的画布,保留对象的副本。此画布的大小为对象宽度/高度。如果我们尝试显示的对象的宽度和高度不正确,图像将被截断。除了禁用对象的缓存来修复问题之外,没有其他解决方案。
目前受影响的用例:
- (自1.7.7版本已修复) 有时候canvas对象看起来模糊
- (自1.7.8版本已修复) 错误解析路径的命令序列(很少)
- (自1.7.3版本已修复) 使用canvas无法测量大小的,自定义超过上边界以及下边界过大的文本
- 组未正确初始化(创建空的组并且在使用.add方法后未更新,请使用addWithUpdate)
- 重置缩放和修改宽度/高度的缩放事件,禁用noScaleCache,将其设置为false
网友评论