Fun with GWT Canvas
Posted by David Chandler on April 29, 2011
One of the things that drew me into programming as a kid was writing simple 2D graphics programs (if you wanted a graphing calculator in those days, you had to write your own). I still remember how excited I was when my junior high math teacher let me write a program on the department’s one and only Apple IIe to graph the rose equation r = cos (nθ). In those days, it took many seconds to draw the figure on screen, which left ample time to reflect on why the number of “petals” on the rose was 2n for even values of n but only n for odd values…
At any rate, one of the reasons I preferred the Apple IIe to my TI-99/4A at home was that the latter had only bitmapped graphics using 8×8 cells, whereas the Apple IIe screen was pixel addressable in a standard x,y grid, just like the 2D canvas in HTML5, which, along with the GWT Canvas wrapper, arrived just in time for the high school Java programming class I’m teaching this year.
My class and I set out to draw equations in polar form but I got carried away when a friend suggested I draw an epitrochoid (it’s the shape of a Wankel engine, thanks for asking). The end result, which uses GWT Canvas and Scheduler (was Timer) may remind you of another childhood toy, but this one doesn’t make any mistakes when the gears slip.
The animation technique used in this demo (as well as the GWT Canvas demo which inspired it) is to obtain a “back” canvas object which is never attached to the DOM. It’s simply never added to the widget hierarchy like the “front” canvas. The rose figure is drawn on the back canvas and accumulates its shape with each frame. The wheels and lines are drawn on the front canvas. To draw each frame, we
- Clear the attached (“front”) canvas
- Copy the image from the unattached (“back”) canvas forward using Canvas.drawImage()
- Draw the wheel / line on the attached (“front”) canvas
The rest is just high school math.
If it runs slowly for you, shrink your browser, as the canvas copy operation take noticeably longer for large canvases. It’s also noticeably faster in Chrome than Firefox, and won’t work in IE until GWT 2.3 (due any day now) adds IE9 support.
If you’re curious about the source, you can find it here:
Drawing a line with GWT Canvas seems a bit more complicated than it should be, but that’s not GWT’s fault, as it’s just a thin wrapper for the HTML5 Canvas API.
back.beginPath(); back.setStrokeStyle(penColor); back.setLineWidth(penWidth); back.moveTo(lastX, lastY); back.lineTo(tx, ty); back.closePath(); back.stroke();
Drawing circles is actually slightly easier because you don’t have to moveTo() the origin first.
front.beginPath(); front.arc(wx, wy, Math.abs(r), 0, PI2); front.closePath(); front.stroke();
Oh! I created the GWT color picker using GWT Canvas, too. It’s very compact (no image download) and uses minimal memory because the RGB color values are cleverly (if I do say so myself) mapped to x,y coordinates using the modulus operator. I love math, I really do.