\( \newcommand{\vecIII}[3]{\left[\begin{array}{c} #1\\#2\\#3 \end{array}\right]} \newcommand{\vecIV}[4]{\left[\begin{array}{c} #1\\#2\\#3\\#4 \end{array}\right]} \newcommand{\Choose}[2]{ { { #1 }\choose{ #2 } } } \newcommand{\vecII}[2]{\left[\begin{array}{c} #1\\#2 \end{array}\right]} \newcommand{\vecIII}[3]{\left[\begin{array}{c} #1\\#2\\#3 \end{array}\right]} \newcommand{\vecIV}[4]{\left[\begin{array}{c} #1\\#2\\#3\\#4 \end{array}\right]} \newcommand{\matIIxII}[4]{\left[ \begin{array}{cc} #1 & #2 \\ #3 & #4 \end{array}\right]} \newcommand{\matIIIxIII}[9]{\left[ \begin{array}{ccc} #1 & #2 & #3 \\ #4 & #5 & #6 \\ #7 & #8 & #9 \end{array}\right]} \)

CS307: Canvas Drawing

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.

Tutorials

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:

  • MDN Canvas Tutorial. This is the best introduction we've found. Some required reading from this tutorial is listed in the next section.
  • W3Schools HTML5 Canvas. W3Schools is a good, comprehensive resource, and has some nice try it yourself features.
  • HTML 5 Canvas Tutorials has the right name, but is possibly better for reference than tutorial.

Reading for Class

Please read the following material about the HTML5 <canvas> element, from the MDN Canvas Tutorial:

  1.  Short intro page
  2.  Basic usage: read all of this, about 5 printed pages (at 100% scale)
  3.  Drawing shapes: read this, stopping before the section on Bezier and quadratic curves, about 9 printed pages
  4.  Applying styles and colors: read the first section, stopping before the section on transparency, about 3 printed pages
  5.  Transformations: read almost all of this, stopping before the section on Transforms, about 7 printed pages. This will be really valuable when we talk about the instance transform in a couple weeks.

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:

  • create a canvas
  • draw rectangles, including filled rectangles
  • draw lines
  • draw circles and arcs
  • choose colors
  • translate, rotate, and scale the coordinate system. This will help when get to the instance transform in Three.js in a couple weeks.

There is code below that you should be able to understand once you've read the tutorial above, together with the JavaScript reading.

Demo: Example 1

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.




Demo: Example 2

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



Demo: Example 3

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





Summary

Here's what I hope you got out of this reading:

  • An HTML canvas has a context object that allows you to do 2D drawings using methods of that object.
  • Rectangles are pretty easy. Arcs are almost as easy. Other shapes are complicated with beginPath() at the start and finishing with fill() or stroke().
  • Fill and stroke colors are pretty straightforward.
  • The drawing is, by default, done in a coordinate system with the origin at the upper left of the canvas and Y increasing downwards.
  • The coordinate system can be changed by the operations of
    • translate
    • rotate
    • scale
  • You can use .save() and .restore() to save a coordinate system, make changes and restore it afterwards.

Reference

A quick cheat sheet reminder:

  • Getting started:
    • 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();