HTML Canvas
<canvas>
is an HTML element used to draw graphics in the browser. Information
on this page is taken from Mozilla's canvas tutorial.
<canvas id="example" width="150" height="150"></canvas>
Use a rendering context to create and manipulate content.
const canvas = document.getElementById('example'); const context = canvas.getContext('2d');
Rectangles
Canvas supports only one primitive shape: rectangles. Three functions exist for drawing rectangles:
fillRect(x, y, width, height)
- Draw a filled rectangle.
strokeRect(x, y, width, height)
- Draw a rectangle outline.
clearReact(x, y, width, height)
- Make the rectangle area transparent.
The x~/~y
parameters are relative to a top left origin.
Paths
Paths are the other primitives in canvas. First, call the beginPath()
method. Then, execute one or more of the following drawing commands. Lastly,
render the path stroke()
and/or fill()
.
moveTo(x, y)
- Lift and move the pen.
lineTo(x, y)
- Draw a line.
arc(x, y, radius, startAngle, endAngle, anticlockwise)
- Draw an arc centered at (x, y).
startAngle
andendAngle
are given in radians.
- Draw an arc centered at (x, y).
arcTo(x1, y1, x2, y2, radius)
- Draw an arc on ending at (x2, y2) with the control point (x1, y1), connected to the previous point by a straight line.
quadraticCurveTo(cp1x, cp1y, x, y)
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
rect(x, y, width, height)
// Line context.beginPath(); context.moveTo(10, 10); context.lineTo(100, 100); context.stroke(); // Triangle context.beginPath(); context.moveTo(50, 50); context.lineTo(100, 100); context.lineTo(50, 100); context.fill(); // Circle context.beginPath(); context.arc(100, 100, 50, 0, Math.PI * 2, true); context.stroke();
Optionally, closePath()
may be called to close the shape by drawing a
straight line from the current point to the start. If the shape has already
been closed or if there's only one point in the list, this function does
nothing. Calling fill()
will close any open shapes and closePath()
is
unnecessary. This is not the case with stroke()
.
Path2D
The Path2D
object efficiently records and plays back drawings. All standard
path methods are available on Path2D
objects. Use stroke()
or fill()
to
draw these objects onto the canvas.
const circle = new Path2D(); circle.moveTo(125, 35); circle.arc(100, 35, 25, 0, 2 * Path.PI); context.fill(circle);
The Path2D
API also provides an addPath
method. This method is useful when
you want to build objects from several Path2D
components.
Styles
Set the fillStyle
and strokeStyle
properties to change the fill and stroke
colors, respectively. Use any CSS color.
context.fillStyle = 'red'; context.fillRect(100, 100, 100, 100);
Set transparency as part of the color or use the globalAlpha
property. This
value (between 0 and 1) applies a transparency value to all future shapes.
context.globalAlpha = 0.2;
Lines may be styled with several properties and functions: lineWidth
,
lineCap
, lineJoin
, miterLimit
, setLineDash(segments)~/~getLineDash()
,
and lineDashOffset
. See this page for more information.
Obtaining crisp lines requires understanding how paths are stroked. Note the situation in the second image below. The area to be filled only extends halfway into the pixels on either side of the path. Be precise to avoid rendering a blurry approximation.
Shapes may be also filled and stoked with gradients and patterns. Use the
createLinearGradient()
and createRadialGradient()
methods to create
gradients. Then, use the addColorStop()
on these objects to denote relative
color positions. Give the createPattern()
method an image to create a
pattern. Gradients and patterns should be handed to the fillStyle
property.
Control shadows with four properties: shadowOffsetX
, shadowOffsetY
,
shadowBlur
, and shadowColor
. shadowColor
is fully-transparent black by
default.
Text
Two methods exist for writing text: fillText(text, x, y)
and
strokeText(text, x, y)
. Change the font and size using the font
property.
context.font = '100px Helvetica'; context.fillText('Hi there', 100, 100);
Other useful properties include textAlign
, textBaseline
, and direction
.
Images
To add an image to the canvas, first get a reference to
HTMLImageElement
. This may be done from scratch (see below) or with a call
like document.getElementById()
. Then, draw the image using the drawImage()
function.
const image = new Image(); image.onload = function() { // Only be executed when the image has finished loading. context.drawImage(image, 0, 0); } image.src = 'example.png';
Note that drawImage()
takes many optional parameters for scaling and slicing
images.
State
Save and restore the state of the canvas with the save()
and restore()
methods, respectively. States are stored as a stack, each save()
pushes,
each restore()
pops. The state consists of the transformations that have
been applied and changes to style attributes.
Transformations
High-Level Transformations
The translate(x, y)
method moves the canvas and its origin to a different point
in the grid. x
indicates the horizontal distance to move and y
the
vertical distance.
The rotate(angle)
method rotates the canvas clockwise around the current
origin by the angle
number of radians. The center point is always the canvas
origin, use the translate()
method to move the canvas.
const width = 100; const height = 100; const x = 50; const y = 50; context.save(); // Translate to the rectangle center, rotate, then translate back. context.translate(x + 0.5 * width, y + 0.5 * height); context.rotate((Math.PI / 180) * 25); context.translate(-(x + 0.5 * width), -(y + 0.5 * height)); context.fillRect(x, y, width, height); context.restore();
Use the scale(x, y)
method to increase or decrease the units in the
grid. Both x
and y
are real numbers. Values smaller than 1.0 reduce the
unit size and values above 1.0 increase the unit size.
Low-Level Transformations
The transform()
, setTransform()
, and resetTransform()
methods provide
raw manipulation of the transformation matrix. Rotation, translation,
scaling, and skewing may all be accomplished using this matrix.
Transformations map coordinates from a one coordinate system into another.
\begin{equation} \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} = \begin{bmatrix} a & c & e \\ b & d & f \\ 0 & 0 & 1 \end{bmatrix} * \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} \end{equation}Translation, scaling, and rotation are equivalent to the following, respectively.
\begin{equation} \begin{bmatrix} 1 & 0 & tx \\ 0 & 1 & ty \\ 0 & 0 & 1 \end{bmatrix} , \begin{bmatrix} sx & 0 & 0 \\ 0 & sy & 0 \\ 0 & 0 & 1 \end{bmatrix} , \begin{bmatrix} cos(a) & -sin(a) & 0 \\ sin(a) & cos(a) & 0 \\ 0 & 0 & 1 \end{bmatrix} \end{equation}A skew transformation along the x-axis and y-axis is equivalent to the following, respectively.
\begin{equation} \begin{bmatrix} 1 & tan(a) & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix} , \begin{bmatrix} 1 & 0 & 0 \\ tan(a) & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix} \end{equation}
The transform(a, b, c, d, e, f)
method multiplies the current
transformation matrix with the matrix described by its arguments. The
setTransform(a, b, c, d, e, f)
method resets the current transform to the
identity matrix, and then invokes the transform()
method with the same
arguments. Lastly, the resetTransform()
method resets the current transform
to the identity matrix.
TODO Compositing and Clipping
TODO Size
Set the component's width and height with JavaScript.
canvas.width = window.innerWidth canvas.height = window.innerHeight
TODO Do we also need CSS?
canvas { width: 100%; height: 100%; }