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 ...

5 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
  4. LEGEND! Panic over.

    ReplyDelete