When fabric object caching is active, the objects you paint on canvas are actually pre painted on another smaller offscren canvas, as big as the object pixel dimension itself. During the `render` method this pre painted canvas gets copied on the main canvas with a `drawImage` operation.
That means that during
scale operations the object is not redrawn on canvas, but just its copied
cached image gets drawn over the canvas.
This feature comes with 3 properties to use it in different ways:
/** * When `true`, object is cached on an additional canvas. * default to true * since 1.7.0 * @type Boolean * @default */ objectCaching: objectCaching, /** * When `true`, object properties are checked for cache invalidation. In some particular * situation you may want this to be disabled ( spray brush, very big pathgroups, groups) * or if your application does not allow you to modify properties for groups child you want * to disable it for groups. * default to false * since 1.7.0 * @type Boolean * @default */ statefullCache: false, /** * When `true`, cache does not get updated during scaling. The picture will get blocky if scaled * too much and will be redrawn with correct details at the end of scaling. * this setting is performance and application dependant. * default to false * since 1.7.0 * @type Boolean * @default */ noScaleCache: true, /** * List of properties to consider when checking if cache needs refresh * @type Array */ cacheProperties: ( 'fill stroke strokeWidth strokeDashArray width height stroke strokeWidth strokeDashArray' + ' strokeLineCap strokeLineJoin strokeMiterLimit fillRule backgroundColor' ).split(' '), /** * When set to `true`, object's cache will be rerendered next render call. * @type Boolean * @default false */ dirty: false,
objectCaching is the main properties, default to true for browsers, false for node, it enables objectCaching at object level.
statefullCache This property rule if fabric should autocheck if is time to redraw the cached copy or if the dev shoud manually invalidate it.
this property is default to false. More on this later.
noScaleCache default to true, disable cache regeneration for scale operation. It can be enabled to avoid blurry effects for big scaling.
cacheProperties Is an array of properties to be checked when statefullCache is on to detect a state change and trigger a cache re rendering.
dirty is a simple flag that force a cache rerender at next render method, and is set to false automatically after cache regeneration.
It depends on what your project looks like. Are you drawing just a bunch of circles, rects and simple plygons? Maybe you will not gain that much performance.
Are you importing and displaying large and complex svgs? well you will move from possibly shuttering to smooth. Is there any glich i should be aware of? Well you may not like the
noScaleCache feature and that is why there is a flag to disable it.
I would say yes, switch to 1.7.0, check if everything is fine. If not report any visual problem to issue tracker, you can still completly disable the feature everywhere doing:
fabric.Object.prototype.objectCaching = false;to ovveride the standard value and cache will be disabled for your project.
Below you can see 2 fabric canvases. The left one is the default chaced one, while the right one is drawn with cache disabled as it was on previous versions.
The canvases are loaded with heavy pathgroups, the snowwhite, the heaviest i could find is in 3 copies and makes the render speed cripple down. Try to drag around one of the shapes on the left or right canvas and notice the speed difference.
Also spot differences in scaling between
noScaleCache with values true or false.
In canvases below Left canvas is
false, that mean that during the scaling tasnformation the obect is not regenerated.
if you scale an object more than 3 times the original size you will notice blurring that then gets fixed with a new cached copy
as soon as you perform a mouse up. Try it by yourself:
Fabric has an hardcoded trigger to update cache during the built in functions where the developer has no an easy way to insert code.
Those situations are:
canvas global zoom.
In all other cases is the developer that is changing some property of an object to detect trigger a change and so he will also set the object to dirty manipulating the
Using the object method
set will do this for you. So calling
object.set('fill', 'red') require no other actions. If for some reason
you are not using the set method ( for example in situation of text objects in wich setting some properties trigger expensive functions ) you will use the flag.
There is also a way to ask fabric to check at render time a change for properties. This is not expensive most of the time but i decided to leave it off because in crowded situations ( like spray brush or 1000+ svg paths ) it was expensive.
A particular note about groups and pathgroups: calling
on a group is not working as expected. Group does not use its own fill property but send the fill property to the children objects. At render time children object are not checked for dirty flag.
This will be addressed in a future version.
Custom subclassing is one of the fabric strongest features in my opinion and object caching has been built with that in mind.. So there is an array defined called
that contains a list of properties that get checked at every render when the property
statefullCache is set true. (defaults to false).
The array looks like this:
cacheProperties: ( 'fill stroke strokeWidth strokeDashArray width height stroke strokeWidth strokeDashArray' + ' strokeLineCap strokeLineJoin strokeMiterLimit fillRule backgroundColor' ).split(' '),
and gets more properties in different sublcasses, for example rect adds
ry and so on.
The properties are checked recursively, that means that at every change detected a copy of the property is saved, and at next render
is compared deeply. Normally properties that need deep checks are gradients, patterns, path array, strokeDash. If your application make no use of some properties at all you can remove them from the cacheProperties array and make the check faster,
or you can add your custom properties that influence rendering to have them checked.
Image is cut of of object bounding box: YES. There is an invisible canvas that keep a copy of the object. This canvas is sized with objects width/height.
If width and height are not correct for the object we are trying to display, the image will be cut off. There is no other solution than disable the caching for the object or fix the problem.
Currently affected uses case:
- paths with wrongly parsed command sequence (very few) - (mainly solved since 1.7.3) Text using custom fonts with very big ascender/descender and of wich canvas is not able to measure extension. - Groups not initialized correctly ( created empty and not updated after using the .add method, please use addWithUpdate)