In this reading, you’ll learn how to draw in 2D on an HTML5 <canvas>
element. Our work this semester will be almost entirely in 3D, using the
sophisticated tools of Three.js. Nevertheless, we’ll wait for a day before
diving into 3D, and start with 2D. This will also give us a chance to play
with JavaScript before getting into the complexities of Three.js.
Many of the readings for this course were written by Scott Anderson, but for this one, he saw no reason to re-invent what has been done very well by others. A web search for html5 canvas tutorial should yield many good results, including the following:
Please read the following material about the HTML5 <canvas>
element, from
the MDN Canvas Tutorial:
In total, this is about 25 printed pages of reading, but there are lots of pictures and the font is large at 100% scale, so it’s not a lot of words. Still, parts of it may be conceptually tough, so don’t underestimate how long it will take. Plus, there’s this webpage itself, and the JavaScript reading.
You are not expected to become perfectly versed in drawing on the canvas, as we’ll spend most of the semester working in 3D using Three.js. Still, you should know how to do the following:
There is code below that you should be able to understand once you’ve read the tutorial above, together with the JavaScript reading.
This first example uses the native canvas coordinate system, with the origin in the upper left and Y increasing down. The canvas is created with a width of 500 pixels and height of 300 pixels.
Here’s the JavaScript code that drew this picture. Please spend some time
making sure you understand this and ask questions. Notice the use of a JS
object sceneParams
to hold a lot of parameters that would otherwise be
separate global variables. Instead, we have just one global variable that
collects all of them.
This is a similar drawing, but this time done in a coordinate system where the origin is at the lower left and Y increases upwards, just like we’re used to from high school. Because the Y location of the house and the smiley are 200 and the height of the canvas is 300, they are located differently from Example 1.
Here is the code that drew this picture. Please spend some time making sure
you understand this and ask questions. You’ll notice, though, that it’s mostly
a matter of having, for example, y+h
instead of y-h
to find the y
coordinate of the top of the house. (Assume that the sceneParams
variable is
the same.)
This is the same drawing, one more time, but now with functions that can be invoked with different translations, rotations, and scaling, to yield different instances. This is a preview of our instance transformation in 3D.
Here’s the code that drew this picture. As before, it’s very similar to our
previous code, but now the functions to draw the house and the smiley don’t
need to add (x,y) to all their coordinates. The coding for them is much
easier, and it’s not much harder to draw an instance. We also can rotate and
scale our objects, which would have been very hard with the coding in versions
1 and 2. (Again, the sceneParams
is the same as before.)
Here’s what I hope you got out of this reading:
beginPath()
at the start and finishing with fill()
or stroke()
..save()
and .restore()
to save a coordinate system, make changes and restore it afterwards.A quick “cheat sheet” reminder:
Add a <canvas>
element to a webpage:
<canvas id="canvasId" width="500" height="300"></canvas>
In JavaScript, get the rendering context for the <canvas>
element:
var elt = document.getElementById('canvasId');
var context = elt.getContext('2d');
rectangles
context.fillRect(x,y,width,height); // draw a filled rectangle
context.strokeRect(x,y,width,height); // draw outline of a rectangle
lines
context.beginPath();
context.moveTo(x1,y1);
context.lineTo(x2,y2);
context.stroke();
shape composed of multiple lines
context.beginPath();
context.moveTo(x1,y1);
context.lineTo(x2,y2);
context.lineTo(x3,y3);
context.closePath();
context.stroke();
filled-in shape with multiple edges
context.beginPath();
context.moveTo(x1,y1);
context.lineTo(x2,y2);
context.lineTo(x3,y3);
context.fill();
arcs
context.arc(centerx,centery,radius,startangle,stopangle,ccw);
colors
context.fillStyle = "blue";
context.strokeStyle = "green";
state stack
context.save();
context.translate(deltaX,deltaY);
context.rotate(angleRadians);
context.scale(xScale,yScale);
context.restore();
This page is based on https://cs.wellesley.edu/~cs307/readings/canvas.html. Copyright © Scott D. Anderson. This work is licensed under a Creative Commons License.