The javascript console can often be opened in a browser by pressing F12.
The canvas element
"The canvas element provides scripts with a resolution-dependent bitmap canvas, which can be used for rendering graphs, game graphics, or other visual images on the fly."
The canvas has been designed for pixel-based graphics, while SVG (Scalable Vector Graphics, another W3C standard) is for vector-based graphics.
Only access elements when the DOM is ready: It's a good practice to have a init function, as we cannot access the elements of the page before the page has been loaded entirely and before the DOM is ready.
Summary:
Declare the canvas
Get a reference to the canvas in a JavaScript variable
Get the context for drawing in that canvas
Specify some drawing properties
Draw some shapes
Drawing Principles
The "stroke" means "wireframe" or "outlined", it is a prefix for setting properties or calling methods that will affect wireframe shapes, "fill" is a prefix for filled shapes.
To set the properties of wireframe shapes use ctx.strokeStyle= ..., for filled shapes use ctx.fillStyle=... So far the values we have used are colors, expressed as strings. Example: ctx.strokeStyle = 'blue';
To draw a wireframe rectangle use ctx.strokeRect(x, y, width, height), to draw a filled rectangle use ctx.fillRect(x, y, width, height);
To set the line width of wireframe shapes, use the ctx.lineWidth property. Example ctx.lineWidth = 10; ctx.strokeRect(0, 0, 100, 100); will draw a 100x100 rectangle in wireframe mode, with an outline width of 10 pixels.
To draw a text message use ctx.strokeText(message, x, y) or ctx.fillText(message, x, y), for wireframe text or filled text respectively.
To set the character font use the ctx.font property; the value is a font in CSS syntax, for example: ctx.font = 'italic 20pt Calibri';
Project 1 (easy): Make a small drawing by just using rectangles and text (a car, a monster, a head, or whatever you like).
Project 2: Make an histogram (bar charts made of filled rectangles) as an array of integer values such as: var data = {1, 12, 20, 14, 13, 9, 5}, for example.
Project 3 (harder, for those who know JavaScript and a little bit of math): Try to draw a human shaped robot using different 2D transforms (translate, rotate). Build a hierarchic skeleton (if we rotate the arm, the forearm and the hand should follow). This can be done by having the function that draws an arm save the context, move the coordinate system, call another function that draws the forearm, that saves the context, move the coordinate system to the end of the arm, call the function that draws the hand, etc. By consecutively calling functions from one another, with each function that saves the context -- moves the coordinate system -- calls another function -- restores the context, we can build a hierarchy of coordinate systems.
Immediate drawing mode: rectangles, text and images
As soon as the ctx.strokeRect(x, y, width, height) or the ctx.fillRect(x, y, width, height) method is called, a rectangle is indeed drawn immediately in the canvas.
Load images in the background, wait for them to be loaded before drawing!
Example with onload function.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh): for drawing sub-images, (sx, sy, sw, sh) define the source rectangle, while dx, dy, dw, sh define the target rectangle. If these rectangles don't have the same size, the source sub-image is resized. Resizing images.
Best practice: only draw an image that is fully loaded, use the onload callback!
Like this.
Project 1 (easy): Make a funny application by mixing all the things seen so far: images, colors, texts, video...
Project 2: Write a small application triggering a screenshot from the Webcam.
Project 3 (a bit harder, need to know how to use CSS positioning and the CSS z-index property): Try to position a canvas on top of a video element and draw shapes on top of the video.
Project 4 (follow-up of project 3): Play two videos in loop mode at the same time, and draw the current image of the video 2 in the canvas on top of video 1, in a smaller size.
Path drawing mode: lines, circles, arcs and curves
Path mode = fill a buffer then execute all buffered orders at once to enable optimization and parallelism.
Call drawing methods that work in path mode, for example call ctx.rect(...) instead of ctx.strokeRect(...) or ctx.fillRect(...)
Call ctx.stroke() or ctx.fill() to draw the buffer's contents,
Beware that the buffer is never emptied, two consecutive calls to ctx.stroke() will draw the buffer contents twice! Instead, use ctx.beginPath() to empty it if needed.
It is possible to empty the buffer by calling ctx.beginPath().
Path drawing is faster than immediate drawing (parallelization is possible).
Warning
Drawing arcs is usually done through a higher level package rather than drawing the arcs one at a time by hand, see the following examples as references and do not try to memorize them.
Important: If you do not want to draw parts of the same path several times, you need to draw two different paths, using the ctx.beginPath() method, as shown in the next example.
Project 1 (easy): Create a small monster using rectangles, arcs, lines, etc. Just drawing a monster head will do the work. Start with something simple: a circle for the head, two squares for the eyes, a line for the mouth, etc., then set some colors and line widths.
Project 2: Same as above but make use of patterns.
Project 3 (harder): Try to draw the current image of a video played in background, hidden using CSS, as the animated background of the canvas.
Project 4 (follow-up of project 3): You can also use the trick with the video to create animated textures for the eyes, skin, etc.