23

I have an image and move it around my web page (JavaScript) like this:

satelliteImage.style.top = coordinates.top + "px";
satelliteImage.style.left = coordinates.left + "px";

Unfortunately, the performance is quite bad in all browsers except Chrome. The bottleneck is rendering speed. I have no hope for IE, but I want to improve Firefox at least. Does anyone have experience with performance of HTML5 Canvas while moving an image, compared to Style change?

Phrogz
  • 296,393
  • 112
  • 651
  • 745
Boris Hamanov
  • 3,085
  • 9
  • 35
  • 58

5 Answers5

61

I have created equivalent tests to compare frame rates for moving an image via CSS versus drawing it on an HTML canvas. Here are the tests:

And here are the FPS results (see URL for test details):

                  Image  Image  Sprite  Sprite
        Browser  Canvas    CSS  Canvas     CSS
----------------------------------------------
  Safari v5.0.3      59     95      59      89
Firefox v3.6.13      59     95      60      90
 Firefox v4.0b8      75     89      78      82
    Chrome v8.0     108    230     120     204
    iPad, Horiz      17     44       2      14
     iPad, Vert       4     75       2      15

As you can see:

  1. You're always going to get better results moving an image as an HTML element than redrawing a portion of the canvas, and
  2. You're likely possibly doing something wrong if you're only getting 5fps.

Edit: Added tests for moving 20 small animated sprites over a background. The conclusions remain the same.

Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • Thanks for the good test Phrogz. Sadly, I don't do anything wrong. When background image loads for example, the frame rate drops drastically. I do not even move the image over it, but over a completely different image that is on top of the background. Both are PNG with a lot of transparency, text with shadow, box shadows, rounded corners etc. You made your test under the perfect circumstances. Yet it demonstrates the point very clearly. Thanks again! – Boris Hamanov Jan 30 '11 at 23:39
  • I thought of something that I could be doing wrong. I use negative coordinates the bring the object outside of its parent area. I remember that I had rendering issues with some browsers when doing this. Am I on the right track? I will test this today. – Boris Hamanov Jan 31 '11 at 06:38
  • 1
    That's the the problem though, if you have a complex page with a lot of visuals the canvas speed will degrade much slower due to it's draw and forget nature, CSS needs to remember all the nodes. It's complicated this stuff. My experience is specifically with game performance (lot's of animated images) where canvas easily outperforms any DHTML. – Jakub Hampl Feb 01 '11 at 18:02
  • @JakubHampl I have added tests for 20 animated sprites (44x70) moving over a 1024x768 static background image. The results are unchanged: letting the native browser compose the result is faster than trying to do it yourself in JavaScript. – Phrogz Feb 01 '11 at 19:41
  • @Phrogz Fair enough. Seems my previous comment was outright wrong :( It would be interesting if @avok00 could post his code so that we could see why is his framerate so low. – Jakub Hampl Feb 02 '11 at 14:00
  • @Phrogz Have you ever tested on computers which have dedicated graphics card? On those computers, drawing on Canvas has better performance thanks to hardware acceleration. – ExpExc Nov 16 '11 at 16:54
  • @ExpExc The results are testing with a MacBook Pro laptop with GeForce GT 330M. I've seen similar results on my Windows desktop with GeForce GTX 285. WebKit also gets [GPU acceleration for CSS animation](http://ariya.blogspot.com/2011/07/fluid-animation-with-accelerated.html); I believe Firefox does, too. – Phrogz Nov 16 '11 at 16:59
  • @Phrogz thanks for the great tools! I ran the tests again and updated them for mobile as well: http://stackoverflow.com/a/13352883/857025 – Don Rhummy Feb 01 '13 at 20:07
  • Interesting, I didn't know that if you move few images dom-manipulation wins. If you need to move more stuff around css-animation (manipulating the dom) is actually slower than canvas. Putting the style-attribute back into the html-elements takes a relative long time, that's why they say "dom-manipulation is expensive". I guess you also find lower canvas frame rates because you do your test with quite a big canvas which has to be redrawn every time. Take a look here for some other tests: http://www.goodboydigital.com/to-dom-or-not-to-dom/ – metatron Dec 12 '13 at 14:28
  • Could you re-run your tests ? Nowadays canvas get hw acceleration too, which back in 2011 was not the case if im right. – user1610743 Feb 17 '14 at 09:48
  • My computers are too fast these days; my simple tests appear to hit framerate limiters. – Phrogz Feb 17 '14 at 14:50
10

It's now been over 2 years and I decided to run these tests to see if this still holds true. It does...and it doesn't.

  1. Firefox Desktop and mobile both run CSS animations significantly faster than canvas.

  2. Chrome desktop runs canvas and CSS animations about the same

  3. Chrome Mobile (on Nexus 7) does the exact opposite: canvas runs significantly faster than CSS!

(Using Firefox Android with Nexus 7 and desktop browsers on Linux with 1920x1080 resolution)


Browser/OS          Canvas Image   CSS IMage   Canvas Sprites   CSS Sprites    
-----------         ------------   ----------  --------------   -----------
Firefox 16          56.7fps        215.6 fps   59.2fps          203.6fps
Firefox 16 Android  17.1 fps       179.6fps    11.5fps          35.7
Chrome 22           192.3fps       223.5fps    170.1fps         164.3fps
Chrome Android      48.3fps        39.9fps     92.8fps          13.1fps

What does everyone else get? Can anyone test IE9, 10 for this?

Don Rhummy
  • 24,730
  • 42
  • 175
  • 330
  • i just ran the test on firefox 21, on a ubuntu system. I get around 220fps for every test except for CSS Sprites which actually drops down to around 120fps. – Spider Jul 04 '13 at 23:19
3

Figured I'd update this old question with my findings on a 3rd generation iPad:

Canvas wins 2:1 with the sprite animations an average of about 120 fps with background clearing toggled both ways. CSS could barely meet 60 fps.

As for the single image, CSS was definitely quicker.

MyNameIsKo
  • 2,171
  • 1
  • 15
  • 24
2

In my experience with Canvas you should be able to get a good 50 fps on Firefox and even a good 15 fps on iOS. IE9 will probably be the fastest browser, other versions don't really implement Canvas.

Jakub Hampl
  • 39,863
  • 10
  • 77
  • 106
  • Thanks! What would be the fastest way to move an image on a canvas? – Boris Hamanov Jan 30 '11 at 12:47
  • @avok00 The only way to move an image on a canvas is to clear the rect where the image was and use `drawImage()` to draw it again. I strongly suspect that your performance will be significantly worse with this, than just moving an image on the DOM, however. – Phrogz Jan 30 '11 at 15:37
  • Hmm, then what is this about 50fps? Maybe I can use translate to move the whole canvas and achieve a better performance? – Boris Hamanov Jan 30 '11 at 18:36
  • @avok00 Jakub's computer is not yours. Write a simple test to compare performance. – Phrogz Jan 30 '11 at 19:31
  • That is the problem. I cannot write a simple test. My site is complex with many layers, drop shadows, css3, background images with a lot of transparency. All that affects performance. I have to almost implement it to make that test :) Otherwize I would not be asking here. My PC is pretty powerfull by the way. FF still sucks at moving the image. No more than 5 FPS. – Boris Hamanov Jan 30 '11 at 21:09
0

Further to MyNameIsKo findings on iPad 3 performance. I was wondering if it was to do with the fact that the CSS DOM method had to worry about drawing on the retina screen of iPad 3 whereas the canvas would be drawn to at lower resolution and then blt'd to screen. An iPad 1 is significantly faster for CSS updates than the iPad3!

I also made some changes to the canvas javascript to be able to draw to a retina resolution canvas. I added the following code after canv.height = h; in the bg.onload function:

if (window.devicePixelRatio) {
    ctx.canvas.style.width = w + "px";
    ctx.canvas.style.height = h + "px";
    ctx.canvas.height = h * window.devicePixelRatio;
    ctx.canvas.width = w * window.devicePixelRatio;
    ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
}

which made a huge reduction in performance...

iPad 1 (iOS 5.5.1)

iPad 3 (iOS 6.1.3)

                      CSS Sprite        Canvas Sprites
-----------------------------------------------------
iPad 1                   90                  100
iPad 3                   55                  120
iPad 1(canvas changes)   n/a                 100
iPad 3(canvas changes)   n/a                 35
Nick Hingston
  • 8,724
  • 3
  • 50
  • 59