2D Drawing with

<canvas>

By Alex Wayne

alex@beautifulpixel.com

http://alexwayne.codes

 

Hack Sonoma County Meetup

6/21/2017

Some of my other canvas creations

Sunscreen

Mandalatron

What's a 2D canvas?

  • A grid of pixels
  • A set of drawing stateful APIs for painting
    • rectangles
    • circles
    • shapes and curves
    • images and gradients
    • text
  • Fast!
  • Animatable!
  • Consistent in conceptual approach on many platforms

The basics

(in Web Browser Javascript)

// HTML
<canvas
  id="canvas"
  width="500"
  height="500"
/>

// JS
let canvas = document.getElementById('canvas')
let ctx = canvas.getContext('2d')

Rectangles

with fills and strokes

ctx.fillStyle = 'red'
ctx.fillRect(50, 50, 100, 100)

ctx.strokeStyle = '#00ff00'
ctx.lineWidth = 5
ctx.strokeRect(200, 50, 100, 100)

ctx.fillStyle = 'rgba(255,255,255, 0.25)'
ctx.fillRect(350, 50, 100, 100)

Paths

connecting vertices

ctx.fillStyle = 'red'

ctx.beginPath()
ctx.moveTo(50, 50)
ctx.lineTo(150, 50)
ctx.lineTo(150, 150)
ctx.closePath()

ctx.fill()

Circles & Arcs

x, y, r, start, end

ctx.beginPath()
ctx.arc(100, 100, 50, 0, 2 * Math.PI)
ctx.fill()

ctx.beginPath()
ctx.arc(250, 100, 50, 0, 1 * Math.PI)
ctx.fill()

ctx.beginPath()
ctx.arc(400, 100, 50, 0, 0.5 * Math.PI)
ctx.fill()

Animate

Clear, Draw, Repeat

const speed = 100 // per second
function draw(elapsed) {
  let seconds = elapsed / 1000
  let x = seconds * speed % 400

  ctx.clearRect(0, 0, canvas.width, canvas.height)
  ctx.fillRect(x, 50, 100, 100)

  requestAnimationFrame(draw)
}
requestAnimationFrame(draw)

The Context

A singular and stateful collection of all your drawing settings

Singular and Stateful

const ctx = canvas.getContext('2d')

ctx.fillStyle = 'red'
ctx.fillRect(0,0,10,10)  // red
ctx.fillRect(10,0,10,10) // red
ctx.fillRect(20,0,10,10) // red

ctx.fillStyle = 'blue'
ctx.fillRect(30,0,10,10) // blue

Settings are remembered for all drawing functions until changed.

Space is stateful, too!

Move the origin around

function drawSquare() {
  ctx.fillRect(50, 50, 100, 100)
}

drawSquare()

ctx.translate(150, 0)
drawSquare()

ctx.translate(150, 0)
drawSquare()

save(), restore()

function drawSquare(x, y) {
  ctx.save() // stash a snapshot of unaltered context

  ctx.translate(x, y) // alter the context
  ctx.fillRect(0, 0, 100, 100) // draw something

  ctx.restore() // undo all context changes since last save()
}

drawSquare(50, 50)
drawSquare(200, 50)
drawSquare(350, 50)

Canvas Transformations

Solar System

function drawCelestialBody(r, dist, color) {
  ctx.save()

  // orbital speed is a function of distance
  let orbitSpeed = 1 / Math.pow(dist, 2)

  // Rotate around
  ctx.rotate(elapsed * orbitSpeed * SPEED)

  // Move "UP" from the center
  ctx.translate(0, dist)
  
  // Draw the celestial body at the origin
  ctx.beginPath()
  ctx.arc(
    0, 0,          // x, y
    r,             // radius
    0, 2 * Math.PI // full circle
  )

  // Set the color and fill it in!
  ctx.fillStyle = color
  ctx.fill()

  crx.restore()
}

Starlit Breeze

Starlit Breeze: Techniques

  • Stars
    • Store array of randomized points
    • Slowly rotate the sky context
  • Moon
    • rotate moon context faster than stars
    • Draw circle off center
  • Tree
    • recursively, to a certain depth, do:
      • ctx.save()
      • Draw a rectangle
      • Move "up" context
      • Rotate context, with a bit of time based variation
      • Scale down context, just a little
      • If at max depth draw a red circle at origin (which will be branch tip)
      • ctx.restore()

By Alex Wayne

alex@beautifulpixel.com

http://alexwayne.codes

 

Hack Sonoma County Meetup

6/21/2017

Made with Slides.com