Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flickering on update canvas JSON with image #3652

Closed
MatBdry opened this issue Jan 26, 2017 · 5 comments · Fixed by #4007
Closed

Flickering on update canvas JSON with image #3652

MatBdry opened this issue Jan 26, 2017 · 5 comments · Fixed by #4007

Comments

@MatBdry
Copy link

MatBdry commented Jan 26, 2017

Hello guys !

I have a weird behavior on load JSON in the canvas, when there is an image in it.

In my case, I would like to update the canvas JSON of a specific canvas (canvas1) every N seconds to have a kind of mirror of another canvas (canvas2). So I get the JSON of the canvas 2, and load this JSON to the canvas1 to have a mirror effect.

Everything is perfect with shape, but when I have one or more image on the canvas, I have a flickering every time I try to update the JSON of the canvas1.

Version

1.7.3

Test Case

http://jsfiddle.net/fmgXt/691/

Steps to reproduce

I added a setTimeout in my jsfiddle code to load the JSON 3 seconds after the first loading. With JSON3, there is no image, so the canvas is updated without flickering.

With JSON2, which contains an image, when the canvas is updated, you have a flickering.

I saw in the code that you made a "clear" of the canvas every time we set a new JSON. But why it's visible when there is an image ? May be a feature could be to use a JSON patch when we update the JSON, to have better performance ?

Thanks for your help !

@asturur
Copy link
Member

asturur commented Jan 27, 2017

The problem is that the loadFromJson take time. The image is restored from its url and this require time.
The canvas clear happens at json load while the repaint happen when all objects are reloaded and there may be some time passing.

Using load from json to have a duplicate canvas is not the fastest solution.
Did you try having the objects referenced by 2 canvases? ( if they are in the same page, otherwise the json is the only solution )

For the flicker part there is nothing we can do. Is the necessary time to load a new image.

@MatBdry
Copy link
Author

MatBdry commented Jan 27, 2017

Ok I understand the problem. But why it's necessary to wait that all objects are loaded to repaint the canvas ? May be it can be a solution to repaint just after the JSON is loaded (for the objects that don't require a latency when we insert them, like shapes, drawings, etc.) and then repaint a second time when all the async objects are loaded ?

Because sometimes, the problem appears just when I move an object on the canvas2 and apply the JSON in canvas1. So the image is in the cache, and the modification in the JSON is just a top / left changing. It could be a solution for me if only the image flicker, because it takes time to load it, but not all the canvas.

thanks for your help !

@asturur
Copy link
Member

asturur commented Jan 27, 2017

i understand what you mean. reloading an image from the cache is anyway a slow operarion. slow enough to flicker.

is not about the speed itself, is just asyncronous. so if you have 4 million paths, the reload will take some seconds, but the cpu will be busy and you will not see any flicker between clear and draw.

image from url, for fast that it can be is still in the event loop and it will be executed after the clear.
so it will flicker.
this is javascript logic, not our own.

yes maybe the clear operation could wait for everything to be loaded and then do all togheter.

not sure it will not break anything. i have to check.

@MatBdry
Copy link
Author

MatBdry commented Jan 27, 2017

Yes it could be a solution ! If you want to test something tell me !

Thanks

@MatBdry
Copy link
Author

MatBdry commented Jan 31, 2017

Hello,

I tried to move the clear operation in the _enlivenObjects function, to call it once the enlivenObjects function has finished. And it works well !

my modifications:

fabric.Canvas.prototype._enlivenObjects = function(objects, callback, reviver) {
            var _this = this;
            if (!objects || objects.length === 0) {
                callback && callback();
                return;
            }
            var renderOnAddRemove = this.renderOnAddRemove;
            this.renderOnAddRemove = false;
            fabric.util.enlivenObjects(objects, function(enlivenedObjects) {
                _this.clear(); // add clear operation here, when all objects are loaded
                enlivenedObjects.forEach(function(obj, index) {
                    _this.insertAt(obj, index);
                });
                _this.renderOnAddRemove = renderOnAddRemove;
                callback && callback();
            }, null, reviver);
        };

edit: the problem is still present in mobile (iPhone 6 Plus)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants