Instantly share code, notes, and snippets.

# qrush/1_intro_to_canvas.md Last active Apr 9, 2017

Canvas tutorial for a high school programming class. Examples and many images based directly off Mozilla's canvas tutorial. Exercises are heavily inspired by it but very different and meant to be done side-by-side. Fork the exercise on Codepen, complete it, and move on! https://developer.mozilla.org/en-US/docs/Canvas_tutorial

# Canvas

Canvas is an awesome HTML tag that we can use through Javascript to make charts, graphs, games, and almost anything you can dream of.

## Get started fast:

In HTML, drop in:

`<canvas id="canvas1" width="300" height="200"></canvas>`

In JS, you'll need:

```var canvas = document.getElementById('canvas1');
var ctx = canvas.getContext('2d');```

Now you've got the "context" object in JavaScript, which we can use to paint on the canvas. Awesome!

Try out drawing some rectangles:

```ctx.fillStyle = "rgb(200,200,0)";
ctx.fillRect(10, 10, 55, 50);

ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
ctx.fillRect(30, 30, 55, 50);```

Full example for reference if needed.

# Shapes

Let's learn how to make more shapes with Canvas.

## The Grid

Coordinate plane starts at the top left. Think of this like a grid from math class. The x, y axis is the same...just you're rotated a bit on your head. You can go in the negative direction too on either axis.

## The Pen

We can tell the canvas how to draw stuff. The way I like to think about this is like we have a giant, stupid pen. Giant since you can really only do one thing at a time with it...and stupid since it does only what you tell it to do. :) Try thinking of it this way, and don't be shy to draw down points on paper.

## Paths

Paths can be used to draw shapes with more (or less!) sides than a rectangle. This is where the "pen" comes into place. `beginPath` drops the pen down, and then we can tell it to `moveTo` around the canvas. This will continue drawing a shape to another point with `lineTo`.

Here's a triangle:

```// Start drawing (upper left point)
ctx.beginPath();
ctx.moveTo(0, 0);

// Draw the upper right point
ctx.lineTo(150, 0);

// Draw lower point
ctx.lineTo(75, 150);

// Fill in the shape!
ctx.fill();```

## Arcs

Canvas is great for drawing curves. Straight lines are boring!

```// ctx.arc(x, y, radius, startAngle, endAngle, antiClockwise);
ctx.arc(75, 75, 50, 0, Math.PI * 2, true);```

The angles are in radians, so we can use `Math.PI` to help us out here. The `antiClockwise` parameter tells canvas which direction to draw the circle in. This can be helpful for drawing half-circles.

## Text

Dropping text into your canvas is easy. Maybe you'll need a score box, show the user's name, or label a graph?

```ctx.font = 'bold 40px impact';
ctx.fillStyle = 'orange';
ctx.fillText("It's Wednesday!", 25, 40);

ctx.font = 'italic 40px impact';
ctx.strokeStyle = 'pink';
ctx.strokeText("It's Wednesday!", 25, 85);```

# Transforms

Transforms let us break the rules of how canvas normally works when drawing to save us time, and make painting things a lot more fun.

## Translate

```// ctx.translate(xPixels, yPixels);
ctx.translate(100, 100);```

Translate "moves" where Canvas thinks (0, 0) is permanently. Put another way, it moves the grid on the x-axis by `xPixels`, and on the y-axis by `yPixels`.

Why do this? If we need to draw a lot of things, it's easier to do this around the origin and translate the shape later.

## Save/restore

```ctx.save();
// do some transformations
ctx.restore();```

Saving gives us a "checkpoint" of what the Canvas' state was. If we call it before we run `translate` or other transformations, it will remember the original clean slate. The `restore` function will go back to the checkpoint created, effectively undo'ing any transform calls you may have run.

Why do this? Calling `ctx.translate(100, 100)` means in order to go back to the original place we were, you'd need to call `ctx.translate(-100, -100)`. Instead of doing more math and creating more work for yourself, just save/restore it.

## Rotation

```// ctx.rotate(radians);
ctx.rotate(Math.PI / 4); // 45
ctx.rotate(Math.PI / 2); // 90
ctx.rotate(Math.PI);     // 180
ctx.rotate(Math.PI * 2); // 360 ```

Remember radians? I hope you do. The strange thing about rotation in canvas is that it doesn't rotate the object you're trying to paint, but rather the entire canvas around the current origin. Crazy!

## Scaling

```// ctx.scale(xScale, yScale)
ctx.scale(2, 2);
ctx.scale(0.5, 0.3);```

Scaling is stretching. Usually on the Canvas, 1 "unit" is 1 pixel on the screen. Scaling lets us bend that rule. If we scaled by `2, 2`, every "unit" is now 2 pixels. You can scale independently in either axis. The default scale is `1, 1`.

# Animation

## Run Loop

Most games and programs that need to run forever (or at least, as long as the user is looking at them) have a "run loop" or "game loop". The basic premise is to respond and react to user input while keeping the core logic of the program running. Here's an example of what a game loop could look like:

In pseudocode:

``````while( user doesn't exit )
check for user input
run AI
move enemies
resolve collisions
draw graphics
play sounds
end while
``````

We're going to be making a simple run loop to animate objects on our canvas. It will basically look like:

``````while
render content (based on changes)
end while
``````

This gives us a clean state every time the run loop starts a new iteration. Based on changes (time, a counter, user input, etc) we can change what is being rendered.

## requestAnimFrame

There are several ways to create a game loop in Javascript. The best current way to do is with `requestAnimationFrame`, a function built into browsers that keeps your loop going while the current browser tab is in focus, and disables the run loop while the user is not looking at the tab.

Since this function isn't working in all browsers yet, we need to use a shim for this, which will be in your forked codepen as `requestAnimFrame`. Kind of lame, but oh well. Here's an example of a game loop using `requestAnimFrame`:

```render = function() {
// draw here
}

run = function() {
render();
requestAnimFrame(run);
}

run();```

All of the code we'll need to worry about here will be in `render`. The `run` function is saved as a variable, and is kicked off at the bottom of the script. Inside of `run`, we call `render` to draw our shapes, and then queue up the next `run` call.