Designing Interactivity

with HTML5 Canvas

What is this workshop about?

Using HTML5 Canvas to allow you to create dynamic, interactive interfaces on the Web

How we going to do that?

(a little) HTML, (a little more) jQuery & (a lot) JavaScript

Workshop overview

Today

Tomorrow

Where did it come from?

It came from Apple OSX Dashboard widgets

What is Canvas?

it's just a HTML5 Tag
see: http://dev.w3.org/html5/2dcontext/

What does canvas let you do?

It let's you draw pixels onto the page. (2D)

What does 3D canvas let you do?

It let's you draw triangles in 3D (WebGL)

Some examples of Canvas

How is the support?

How do we use it?

  1. Add it on the page

  2. Get the drawing context

  3. Draw something onto it

1. Add it to the page.

Need to declare a HTML5 doctype, write some HTML, and add a Canvas tag with a width and a height.

2. Getting the rendering context

The context is actually what we use to draw on the page.


var canvas = document.getElementById('canvasElem');
var ctx = canvas.getContext && canvas.getContext('2d');

if(!ctx) {
   // No 2d context available, let the user know
   alert('Please upgrade your browser');
} else {
  // Do something
}

3. Draw something

Use ctx.fillStyle ="COLOR" and ctx.fillRect(x,y,w,h) to draw some rectangles no the screen.

A Quick Note

From now on, we're just going to show the JavaScript. The last slide just becomes:

Actually we'll make it even shorter:

Using jQuery selector and putting the getContext on the same line.

Other stuff we can draw:

  1. More rectangles

    ctx.fillRect(x,y,width,height)
    
    ctx.clearRect(x,y,width,height)
    
    ctx.strokeStyle = "#000000";
    ctx.strokeRect(x,y,width,height)
    
  2. Lines

    ctx.beginPath();  
    ctx.moveTo(x,y);  
    ctx.lineTo(x,y);  
    ctx.lineTo(x,y);  
    ctx.fill(); or ctx.stroke();
    
  3. Arcs

    ctx.beginPath();
    ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise)
    ctx.fill(); or ctx.stroke();
    
  4. Setting the opacity

    ctx.globalAlpha = 0.2;
    ctx.fillRect(x,y,width,height);
    
  5. More: https://developer.mozilla.org/en/Canvas_tutorial/Drawing_shapes

  6. Fill Styles: https://developer.mozilla.org/en/Canvas_tutorial/Applying_styles_and_colors

Draw a picture:

Snow man?

Where's the interactivity?

To get interactivity, we need to listen for events

Listening for events with JavaScript

Listening for events with jQuery

Once again, jQuery makes our life easier, and use $("elem").on(..) to bind with a consistent event object. (Make sure you have a 1.7 or higher version of jQuery)

what's in the event

Let's examine the event Object

Getting the X and Y

Let's examine the event Object (Open up the console)

Bad news: offsetX and offsetY aren't universally supported (WebKit only)

Workaround is to calc it yourself. We're going to skip this in these slides for simplicity's sake and assume you are using Chrome to view this.

Draw a square

Draw a 4x4 square centered on the mouse cursor.

Draw a random color square

Drawing some lines

Draw use beginPath, moveTo, lineTo to draw lines on mousedown and mousemove.

What about the keyboard?

We can listen for keypress, keydown and keyup events

Listening for keyboard events

Listening the arrow keys

The arrow keys are sort of difficult to get at, as we need know the keycodes to get at them. Also the arrow keys don't send keypess events.

Drawing Circles under the keyboard

Drawing colored under the keyboard

What about animation?

To get animation, we need to switch from event-driven drawing to timer-driven drawing

Timers in JavaScript

  1. setInterval - call repeatedly

    function animationLoop() {
       // Run some code
    }
    
    var loopTimer = setInterval(animationLoop,30);
    
  2. setTimeout - call once

    function animationLoop() {
       // Run some code
       loopTimer = setTimeout(animationLoop,30); 
       // pass a callback + # of milliseconds
    }
    
    var loopTimer = setTimeout(animationLoop,30);
    
  3. clearInterval / clearTimeout

    clearInterval(loopTimer);
    // or
    clearTimeout(loopTimer);
    

Which is best?

Neither - requestAnimationFrame, which works like setTimeout but let's the browser control the animation. But for now, use setTimeout

Animating Objects

  1. Position based on velocity

    x = x + vx * dt;
    y = y + vy * dt;
    
  2. Velocity based on acceleration

    vx = vx + ax * dt;
    vy = vy + ay * dt;
    
  3. All to together now

    vx += ax * dt;
    vy += ay * dt;
    
    x += vx * dt;
    y += vy * dt;
    

Make a Ball fly through the air

Make a Ball fly through the air

Images

Canvas also let's you draw images

Need to have image objects first

  1. Can pull the from the page:

    <img src='images/penguin.png' id='penguin'/>
    <script>
    // Wait for page to finish loading
    $(function() {
      var img = $("#penguin")[0];
      // Do something with img
    });
    </script>
    
  2. Can load entirely in JavaScript

    <script>
      var img = new Image();
      img.onload = function() {
        // We can use image
      }
      img.src = 'images/penguin.png';
    </script>
    

Drawing images on Canvas

  1. Simplest, just pass an image and a x and y

    ctx.drawImage(img,x,y);
    
  2. Can also pass a destination width and height

    ctx.drawImage(img,x,y,dw,dh);
    
  3. Or at it's most complicated:

    ctx.drawImage(img,sx,sy,sw,sh,dx,dy,dw,dh);
    

Let's exercise image drawing

Make an image stamper

Make the penguin follow the mouse

penguin vs. mouse *slowly*

Transforms

Canvas supports the idea of a transformation matrix that you can translate, rotate, and scale around.
https://developer.mozilla.org/en/Canvas_tutorial/Transformations

Pulsating Snowflake

Order is very important!

Particle System

  1. A bunch of small objects that are animated and have some behavior and a lifetime

  2. Can store them in an array

     var particles = [];
    
  3. Can create a particle object prototype to draw and update

    var Particle = function() { /* Initialize */ }
    Particle.prototype.update(ctx) { /* Update the particle */ }
    Particle.prototype.draw(ctx) { /* Draw the particle */ }
    
  4. Can just loop over all of them to update an draw

    for(var i = 0, len = particle.length; i<len; i++) {
      var particle = particles[i];
      particle.update(dt);
      particle.draw(ctx);
    }
    

Particle Lifetime

  • If they have a lifestime, we need to handle removing them

    removedParticles = [];
    for(var i = 0, len = particle.length; i<len; i++) {
      var particle = particles[i];
      particle.update(dt);
    
      if(particle.dead) { removedParticles.push(particle); }
    
      particle.draw(ctx);
    }
    
    for(var k =0;k<removedParticles.length;k++) {
      var idx = particle.indexOf(removedParticles[k]);
      // If particle is found
      if(idx != -1) {
        particles.splice(idx,1);
      }
    }
    
    
  • Random Colored Twinkling Lights

    Starfield

    Turn the twinkling lights into a flying starfield

    Putting it all together