1.7.6
https://jsbin.com/bofiraj/1/edit?js,output
zooming in and out will be more responsive
zooming in and out takes many seconds
In this test case we only have 1k elements. Our real maps need to support upwards of 4k elements. I would like to know what I can do to make this more efficient. Once zoomed the performance is pretty good it is just the zooming functionality itself that is not responsive.
If you determine this is outside of the scope of your library would you be interested in some consulting work to help us with our specific issue? If so, please let me know how to go about coordinating that.
Your test case consumes a lot of memory too.
With IE11 / Win 7 the Task Manager shows an additional 8 GB while zooming in. This memory is released while zooming out.
I think with 4k elements many users will have a serious memory shortage.
Do you know why this would utilize 8gb of RAM during zoom? Is there a different way to structure the canvas?
Sorry, don't know. I'm just using fabricjs in a project.
As a wild guess, it might have to do with the (fairly new) caching.
Caching can be disabled: Fabric.js Object caching
You are adding path-objects in your test case. Do you have the same problem with "simpler" objects, like rectangles or circles?
var rect = new fabric.Rect({
left: 10,
top: 10,
fill: 'red',
width: 20,
height: 20
});
canvas.add(rect);
SVGs are mandatory for my needs. We haven't noticed objectCaching making any difference to the zoom performance.
i ll have a look, i m interested in optimizing this anyway.
I have some ideas, i ll give a look at your test case first.
So your use case problem is this:
When zooming the canvas cache for that little svg gets update.
All 1000 canvases gets an update, that means that from a little let's say 50x50 svg to zoom 30 you go to 1500 x 1500.
1000 thousands small canvases gets discarded and resized 30 times bigger and repainted with the same simple svg.
In your case the cache is more a problem than a benefit.
If you disable the cache, you will notice that the zoom is istantaneous but when you drag the objects around is laggish.
You should make the best of both world, maybe you can do without modify the library.
How this map should work in the real app? do you have a picture?
mean time give a read to
from 50x30 to 1500x900
1500x900x4 byte per pixel is 5.4Megabyte per object. 1000 objects is 5.4 gigabytes of canvases all around. I'm surprised it does not crash
@asturur
We start out at 100%, which basically means you can see the entire canvas area. So depending on the resolution of the display, we calculate what zoom things would have to be to fit 100% of it on the screen. From there we move in increments of 5 all the way up to 50x whatever 100% was.
All of the objects are interactive, the map pans using relativePan(), which works nicely even at a high zoom. The objects on the map move perfectly fine too (once zoomed). It is mainly the zooming that takes forever.
are the object all same and they just change color and dimensions?
They are completely different SVGs with different sizes and shapes. The pictures above are just a playground I setup to benchmark performance. It has about 2500 objects on it. I just kept adding the same SVG over and over but we have a hundred different ones and that will keep growing. They are roughly similar in size +/- 10 - 20 pixels
your best bet would be use the isOffScreen method.
take that demo you did, after zoom, go trough object and check object.isOnScreen().
Most of the object should return false, at that point you can skip rendering of them and maybe get good performance in most of the cases
I am unsure what that looks like to specifically render one set of objects but not the next.
perform zoom -> canvas.forEachObj -> obj.isonscreen -> obj.render
Above is my assumption of what I think would need to happen but not sure since zoom seems to be global to the entire map.
Also, since you can pan in our app while zoomed, would this defeat the purpose?
So this would divide the quantity of canvases to update at once.
You need to override some fabric method, i'll try to leave an example fore you in the fiddle.
I cannot save the fiddle since i do not have the account and i do not like pastebin.
use this 4 lines
const originalRender = fabric.PathGroup.prototype.render;
fabric.PathGroup.prototype.render = function(ctx, noTransform) {
if (!this.isOnScreen()) {
return
}
return originalRender.call(this, ctx, noTransform);
};
you should see a massive performance boost in zooming.
I see MASSIVE really.
Let me know how it works for panning.
@asturur This is a night and day difference. This worked like a champ. Are there any consequences I should be worried about? If not, I would consider this closed and probably introduce this change to your next release!
you should check.commit.of today for a better onscreen check if it does not give a speed issue.
i cannot think of drawback for now, let me know if you find them.
was an idea i had from some time, did not find time to test it
Proposed changes solved performance problem
Most helpful comment
i ll have a look, i m interested in optimizing this anyway.
I have some ideas, i ll give a look at your test case first.