+ 26
What is the optimal way to smoothly animate 10000+ points in HTML Canvas?
As the question stated, I want to animate 10000+ independent points in canvas. What is the best approach so that the animation runs smoothly or at least increase fps rate? Is WebGL the only solution? Multiple canvases? Or is there a way to do it in plain JS? So here's my sample code: https://code.sololearn.com/W0HtmZpcC9xj/?ref=app The code only has 100 points. If I increase it to 1000, the animation lags significantly. At 10000, it's like 2fps.
20 Answers
+ 16
I made some changes directly to your routines and am getting 6-10x increase here:
https://code.sololearn.com/WO0MnC7W46L0/?ref=app
Changes:
prebind function to set 'this' context (fn = ...)
preload function with locals (this.vars) to reduce variable scope thrashing
call RAF at end of init so that events run before first frame (instead of after)
added timestamp and fps tally
made main loop variable semi-local (var keyword on 'j')
* moved beginPath, fills and closePath out of critical loop
moved RAF to top of frame function
dubious: removed canvas wipe function, moved to frame fn
* Probably biggest change
Optimizations past this without going the GPU route (which is fraught with trickery) include workers (you can safely run 2 workers per navigator.hardwareConcurrency value):
https://code.sololearn.com/Wm9FGmaEs1Ao/?ref=app
Accelerated datatypes (set multiple bytes at a time instead of 1):
https://code.sololearn.com/WBp7kFYTlyac/?ref=app
I can add more but I'm on way later than usual.
+ 24
You've successfully created a benchmark tool lol.
+ 17
Since webgl is not supported by some devices, i would also suggest making your for loop asynchronous, draw elements independently in a separate animation frame and call that frame for each element inside your for loop, this way the next points would not await for the previous points to complete rendering and would happen simultaneously.
+ 15
10000 runs smoothly
20000 some lag
>= 30000 significant lag
tested on: Huawei p9
I suggest webgl which runs on gpu and multiple canvases to make it faster.
+ 10
JonathanP If you can merge a few elements into one and animate that one element instead a few individually, that should reduce the load. However, if the question is solely about animating different canvas elements, then my answer wouldn't be valid and I don't have any. :>
P.S. Mine slows down around 5000.
+ 10
JonathanP i saw your question late.
You can animate 10000,20000,30000 points with purejs and canvas.
it comes at an expense.
reduced graphics buts its worth it.
use the ctx.createImageData() Method
this code...has 20000 individual points
https://code.sololearn.com/WegRzh0755ZG/?ref=app
+ 7
Hatsy Rei , apparently, each element should be independent.
But on second thought, maybe I can group some elements with similar behaviors and animate as one.
Thanks.
+ 7
Note caveats I've read/tried:
Multiple RAFs / timers worth a shot, may step on each other (making things worse) if you're saturating JS's main (only) foreground thread. I've got a test to show this interference but I'm not sure it's quite ready yet (just try it).
Multiple canvases draw acceleration help seems to depend on the webview and may not help as much in later versions (if memory serves).
...
+ 6
Thanks Haris , I'll try multiple canvases first. I'm not familiar with WebGL yet.
+ 5
Unfortunately, not possible in pure js.
+ 5
Thanks a lot Kirk Schafer. That was quite an extensive solution. I'll delve on each one.
+ 4
In an iPhone7 your code runs smoothly using 10000 points. Indeed it is smooth until 30000 points. At 50000 there is lack of smoothness, at 100000 it gets to 2 fps.
To increase code speed you could use temporary variables instead of looking after array[j].x seven times. Memory retrieval time should be improved. Use like tmpX=array[j].x; if tmpX>... ;...;...; tmpX=12; ...;...;...; array[j].x=tmpX.
+ 4
᠌᠌brains how I remember that code ~ great code ~
I have to agree with Haris ,and Valen.H. ~
There is always going to be some lagging but as to how much can best be based by handler by layers. Plus easier to fix based on which one rips over in the overload.
+ 4
BroFarOps Sorry, I'm having some hardware issues and I missed this. If you want I can try to answer something in a related code comment (?) and then maybe post a summary here if an addendum is useful... Otherwise I can try to fill in an answer with related / active questions where you're contributing.
+ 3
Andre Daniel , If it's not possible, then I guess I have to resort to WebGL or any other engine. Thanks.
+ 3
Edward , thanks for the suggestion. I haven't thought of reducing repetitive memory retrieval. I'll look at some other redundant parts.
+ 3
Kirk Schafer will it continue to accelerate without a point of crashing... By the way, good codes. Also at what point is there nolonger identifiable ? ( sheet color ~ no metrix ? )
+ 3
Thanks ᠌᠌brains. I'll look into that one.
+ 2
Kirk Schafer I understand oh to well hardware issues ~
I reread my comment
'Kirk Schafer will it continue to accelerate without a point of crashing... By the way, good codes. Also at what point is there nolonger identifiable ? ( sheet color ~ no metrix ? )"
You gave an answer: I excepted the response and pretty much left it as your current best answer at the time.
I believe Jonathan Pizarra received his best answer so I had completely left thought and topic.
- 1
thanks