Drawing APIs: SVG and Canvas

  • yesterday's slides: http://j.mp/slides-ntu
  • yesterday's code: http://j.mp/code-ntu (day1 directory)

http://caniuse.com

SVG

Scalable Vector Graphics

<svg>
  <rect x="400px" y="100px" width="150" height="150"
        style="fill:blue;stroke:pink;stroke-width:5;fill-opacity:0.1;stroke-opacity:0.9" />
  <circle cx="400px" cy="100px" r="100px" fill="green"
          stroke="orange"/>
</svg>
            

Benefits

Easy to scale and script image

Scaling

Image scaling vs SVG.

Scripting


var circle = document.getElementById("greencircle");

circle.addEventListener("click", function(el){
  var r = parseInt(this.getAttribute("r"), 10);
  r += 10;
  this.setAttribute("r", r);
});
            

Other SVG Types

Other SVG types include arcs, paths, lines, and polygons
http://www.w3schools.com/svg

Canvas (Two Dimensional Context)

https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial

Rectangles

  • ctx.drawRect(x, y, width, height)
  • (0,0) is upper left

<canvas id="drawing-space" height=200 width=200></canvas>
          

var canvas = document.getElementById("drawing-space");            
var ctx = canvas.getContext("2d");

ctx.strokeStyle = "#999";
ctx.strokeRect(0,0,canvas.width, canvas.height);
ctx.fillStyle = "#022448";
ctx.fillRect(75,75,50,50);
          

Lines

ctx.moveTo(x,y) and ctx.lineTo(x,y)

var canvas = document.getElementById("drawing-space");
var ctx = canvas.getContext("2d");

var height = canvas.height, width = canvas.width;
ctx.strokeStyle = "#000";

ctx.beginPath();
ctx.moveTo(width / 2, 0);
ctx.lineTo(width / 2, height);
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle = "#0F0";
ctx.moveTo(0, height / 2);
ctx.lineTo(width, height / 2);
ctx.stroke();
          

Arcs

ctx.arc(x, y, beginRadian, endRadian, antiClockwise)

ctx.beginPath();
ctx.arc(75,75,50,0,Math.PI*2,true); // Outer circle
ctx.moveTo(110,75);
ctx.arc(75,75,35,0,Math.PI,false);   // Mouth (clockwise)
ctx.moveTo(65,65);
ctx.arc(60,65,5,0,Math.PI*2,true);  // Left eye
ctx.moveTo(95,65);
ctx.arc(90,65,5,0,Math.PI*2,true);  // Right eye
ctx.stroke();
          

Text

ctx.fillText(text, x, y);

ctx.font = "40pt Arial";
ctx.fillText("hello NTU", 50, 100);
          

Fill Patterns

ctx.createPattern(image, mode);

var image = new Image();
image.addEventListener("load", drawText);
image.src = "../img/jacob/distressed.jpg"

function drawText(){
  var pattern = ctx.createPattern(image, 'repeat');
  ctx.fillStyle = pattern;
  ctx.strokeRect(0,0, canvas.width, canvas.height);
  ctx.font = "40pt Arial";
  ctx.fillText("hello NTU", 50, 100);
}
          

Save Context

  • ctx.save() saves current settings
  • ctx.restore() restores previous settings

ctx.fillStyle = "rgba(237,32,186,0.5)";
ctx.fillRect(0,0,100,100);
ctx.save();

ctx.fillStyle = "rgba(10,10,10,0.5)";
ctx.fillRect(40,40,100,100);

ctx.restore();
ctx.fillRect(80,80,100,100);            
          

Simple Draw Image

ctx.drawImage(image, x, y, width, height);

var image = new Image();
image.addEventListener("load", drawTheImage);
image.src = "../img/jacob/unicorn.jpg"

function drawTheImage(){
  ctx.drawImage(image, 100, 0, 100, 100);
  ctx.drawImage(image, 250, 0, 200, 200);
}
          

Segment Draw Image

ctx.drawImage(image, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight);

var image = new Image();
image.addEventListener("load", drawTheImage);
image.src = "../img/jacob/unicorn.jpg"

function drawTheImage(){
  ctx.drawImage(image, 300, 0, 200, 200, 0, 0, 400, 400);
}
          

Text + events


canvas.addEventListener("mousemove", drawCoords);

function drawCoords(evt){
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.strokeRect(0,0, canvas.width, canvas.height);
  var rect = canvas.getBoundingClientRect();
  var x = evt.clientX - rect.left;
  var y = evt.clientY - rect.top;
  ctx.font = "24pt Arial";
  ctx.fillText("(" + x + "," + y + ")", 50, 100);
}
          

Simple Paint Brush

Simple Paint Brush


canvas.addEventListener("mousedown", mouseDown);
canvas.addEventListener("mouseup", mouseUp);
canvas.addEventListener("mousemove", drawCoords);
var down = false;

function mouseDown(evt){
  down = true;
}

function mouseUp(evt){
  down = false;
}

function drawCoords(evt){
  if(down){
    var rect = canvas.getBoundingClientRect();
    var x = evt.clientX - rect.left;
    var y = evt.clientY - rect.top;
    ctx.fillRect(x-5,y-5,10,10);
  }
}            
          

Advanced demo: Putting it all together:

  • http://j.mp/asteroid-canvas
  • http://chimera.labs.oreilly.com/books/1234000001654/ch08.html

Advanced demo: With Physics

http://andrew-hoyer.com/experiments/cloth/