iconfu iconfu iconfu is the world's largest collection of free, open-source icons and it comes with a handy image editor, so you can tweak icons to suit your needs exactly or even draw your own from scratch
invert blue resize move up verbose drawmode lighter previews remove swap animator library library draw shift up make a copy large editor explorer your icon contract agreement tag

15 November 2010

HTML5 Canvas terribly slow drawing lines [not]

Quick heads-up if your canvas application is running awfully slowly, and you're using beginPath(), moveTo(), and/or lineTo().

A simple interpretation of canvas documentation suggests this is a fine way to draw a series of parallel lines (as one might do if one was for example drawing a background grid on one's canvas) ...


  for (var here = start; here < end; here += interval) {
    cx.beginPath();
    cx.moveTo(here, top);
    cx.lineTo(here, bottom);
    cx.stroke();
  }

One would be terribly, terribly wrong! Well, not wrong exactly, but awfully slow ... try this instead


  cx.beginPath();
  for (var here = start; here < end; here += interval) {
    cx.moveTo(here, top);
    cx.lineTo(here, bottom);
  }
  cx.stroke();

The beginPath() and stroke() calls are only needed once each per refresh. My grid drawing dropped from 40ms to 3ms with this change. Not bad ...

4 comments:

  1. thank you!! :)

    ReplyDelete
  2. I'll be honest here- I actually tried moving stroke() outside of the loop right off the bat to see if it would go - it did, but for me it did little (if nothing) to alleviate the problem.

    I ended up on this page by searching for a solution, but see you're recommending what I am already trying without success. >_<

    Do you have any other ideas what could be the culprit.

    I'm doing a simple 10x20 grid, expected at 30 FPS. The frames per second almost immediately plummet to about 5 FPS on a good browser (1 or lower on Firefox). Commenting out the grid will kick the FPS back up to the expected frame-rate.

    Are we expected to generate the grid once, save it as raw image data, and then on subsequent frames use the image data to draw the grid?? I sure hope not because of a few issues I see this bringing up (if the grid isn't the first thing drawn, etc..)

    I have been reading that the Canvas API in HTML5 is supposed to provide access to quite low-level calls - but something as simple as this should never cause this much slow down when you can get away with thousands of lines/shapes in things like directX/openGL.

    ReplyDelete
  3. Okay, I figured out the solution to my scenario:

    I wasn't including the call to beginPath() at all (inside or outside of the loops). I had assumed this was unnecessary since it still works and didn't cause performance hits elsewhere.

    Make sure you include a call to beginPath() OR ELSE.

    Also, it can't hurt to be proper and include closePath() - that is currently left out on this example here.

    ReplyDelete