Overview

Overview

What is Canvas?


<html> 
<body> 
<canvas width='300' height='200' id='canvas'></canvas> 
<script> 
var canvas = document.getElementById('canvas'); 
var c = canvas.getContext('2d'); 
c.fillStyle = 'red'; 
c.fillRect(25,25,200,150); 
</script> 
</body> 
</html> 

	

What is Canvas?

Which? What? When?

So where does it fit in with the rest of the web?

Browser Support

http://caniuse.com/#feat=canvas

Basic Drawing

Simple Drawing

Canvas is a simple 2D API.

  1. Get a reference to a graphics context.
  2. Set some properties, then draw something.

		
	

Simple Drawing

Canvas is a simple 2D API.

  1. Get a reference to a graphics context.
  2. Set some properties, then draw something.

		
	

Paths

Canvas only directly supports the rectangle shape. To draw any other shape you must draw it yourself using a path.


		
	

Coordinate System

Images


		
	

Images - spec

This method can be invoked with three different sets of arguments:

Each of those three can take either an HTMLImageElement, an HTMLCanvasElement, or an HTMLVideoElement for the image argument.

context . drawImage(image, dx, dy)
context . drawImage(image, dx, dy, dw, dh)
context . drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)

Draws the given image onto the canvas. The arguments are interpreted as follows:

The sx and sy parameters give the x and y coordinates of the source rectangle; the sw and sh arguments give the width and height of the source rectangle; the dx and dy give the x and y coordinates of the destination rectangle; and the dw and dh arguments give the width and height of the destination rectangle.

If the first argument isn't an img, canvas, or video element, throws a TypeMismatchError exception. If the image has no image data, throws an InvalidStateError exception. If the one of the source rectangle dimensions is zero, throws an IndexSizeError exception. If the image isn't yet fully decoded, then nothing is drawn.

Text


		
	

Text - spec

http://dev.w3.org/html5/2dcontext/#dom-context-2d-filltext

measureText must return the new TextMetrics object. TextMetrics have only width value.

Gradients


		
	

Gradients


		
	

Gradients - spec

http://dev.w3.org/html5/2dcontext/#dom-context-2d-createlineargradient

Making Charts

Making Charts

1. Create A New Page

<html>
<body>
<canvas width="500" height="500" id="canvas-chart"></canvas>
<script>

var data = [ 16, 68, 20, 30, 54 ];

</script>
</body>
</html>

Making Charts

1. Create A New Page

		
	

Making Charts

1. Create A New Page

Making Charts

2. Add Data

		

Making Charts

2. Add Data - rect spec

http://dev.w3.org/html5/2dcontext/#dom-context-2d-fillrect

Making Charts

2. Add Data

		

Making Charts

3. Add Line and Label

		

Making Charts

3. Add Line and Label - fixed position and color

		

Making Charts

Piechart

		

Paths-spec

http://dev.w3.org/html5/2dcontext/#dom-context-2d-arc

Paths-spec

http://dev.w3.org/html5/2dcontext/#dom-context-2d-arc

Paths-spec

http://dev.w3.org/html5/2dcontext/#dom-context-2d-arc

Paths-spec

http://dev.w3.org/html5/2dcontext/#dom-context-2d-arc

Paths-spec

http://dev.w3.org/html5/2dcontext/#dom-context-2d-arc

ArcTo Drawing


		
	

Arc Drawing


		
	

Advanced Drawing and Events

ImageData

getImageData / putImageData

cross-origin problem

			var canvas = document.getElementById('canvas-ImageData1'); 
			var ctx = canvas.getContext('2d');
			var objImageData;

			var img = new Image();
			img.onload = function() {
				ctx.canvas.width = img.width;
			    ctx.canvas.height = img.height;
				ctx.drawImage( img, 0, 0 );

				try {
					try { 
						objImageData = ctx.getImageData(0, 0, img.width, img.height)  
					} catch (e) { 
						netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
						objImageData = ctx.getImageData(0, 0, img.width, img.height) 
					}
				} catch (e) {
					throw new Error("unable to access image data: " + e)
				}
			}
			img.src = "./images/html5icon2.png";
 
			alert("Pixel an (0,0): rgba("+objImageData.data[4]+", "+objImageData.data[5]+", "+objImageData.data[6]+","+objImageData.data[6]+")");
		

ImageData-spec

http://dev.w3.org/html5/2dcontext/#pixel-manipulation

Image Pattern

original image

	    
	

Image Pattern-spec

http://dev.w3.org/html5/2dcontext/#dom-context-2d-createpattern

Opacity


		
	

Opacity-spec

http://dev.w3.org/html5/2dcontext/#dom-context-2d-globalalpha

Transforms


		
	

Transforms-spec

http://dev.w3.org/html5/2dcontext/#dom-context-2d-translate

State

		function testDraw(id, num) {
			var ctx = $("#"+id+" > canvas")[0].getContext('2d');

			switch( num ) {
			case '1':
				ctx.fillStyle = '#FA6900';
				ctx.shadowOffsetX = 5;
				ctx.shadowOffsetY = 5;
				ctx.shadowBlur    = 4;
				ctx.shadowColor   = 'rgba(204, 204, 204, 0.5)';
				ctx.fillRect(10,10,15,150);
				break;
			case '2':
				ctx.fillStyle = '#E0E4CD';
				ctx.shadowOffsetX = 10;
				ctx.shadowOffsetY = 10;
				ctx.shadowBlur    = 4;
				ctx.shadowColor   = 'rgba(204, 204, 204, 0.5)';
				ctx.fillRect(40,10,30,150);
				break;
			case '3':
				ctx.fillStyle = '#A7DBD7';
				ctx.shadowOffsetX = 15;
				ctx.shadowOffsetY = 15;
				ctx.shadowBlur    = 4;
				ctx.shadowColor   = 'rgba(204, 204, 204, 0.5)';
				ctx.fillRect(100,10,45,150);
				break;
			case '4':
				ctx.beginPath();
				ctx.arc(195, 85, 22, 0, Math.PI*2, true);
				ctx.closePath();
				ctx.fill();
				break;
			case '5':
				ctx.beginPath();
				ctx.arc(270, 85, 15, 0, Math.PI*2, true);
				ctx.closePath();
				ctx.fill();
				break;
			case '6':
				ctx.beginPath();
				ctx.arc(315, 85, 8, 0, Math.PI*2, true);
				ctx.closePath();
				ctx.fill();
				break;
			default:
				//ctx.clearRect(0, 0, 350, 180);
				ctx.fillStyle = 'white';
				ctx.fillRect(0,0,350,180);
				break;
			}
		}
		function saveStateTest(id) {
			var ctx = $("#"+id+" > canvas")[0].getContext('2d');
			ctx.save();
		}
		function restoreStateTest(id) {
			var ctx = $("#"+id+" > canvas")[0].getContext('2d');
			ctx.restore();
		}
		function initStateDemo() {
			var ctx = $("#statedemo > canvas")[0].getContext('2d');
			ctx.fillStyle = 'white';
			ctx.fillRect(0,0,350,180);
		}
		initStateDemo();
		
reference : http://html5.litten.com/understanding-save-and-restore-for-the-canvas-context/

State-spec

http://dev.w3.org/html5/2dcontext/#dom-context-2d-save

Clipping


	    
	

Clipping-spec

http://dev.w3.org/html5/2dcontext/#clipping-region

Event

c.beginPath();
c.arc(
    100,100, 40,  //40 pix radius circle at 100,100
    0,Math.PI*2,  //0 to 360 degrees for a full circle
);
c.closePath();
var a = c.isPointInPath(80,0);     // returns true
var b = c.isPointInPath(200,100);  // returns false

Event-spec

http://dev.w3.org/html5/2dcontext/#hit-region

Event

Event-spec

http://dev.w3.org/html5/2dcontext/#dom-context-2d-ispointinpath

Event

		function hitTest() {
			var canvas = document.getElementById("hittestdemo2");
			var ctx = canvas.getContext('2d');
			ctx.fillStyle = 'white';
			ctx.fillRect(0,0,300,200);

			ctx.beginPath();
			ctx.fillStyle = 'blue';
			ctx.rect(100,50,100,100);
			ctx.fill();

			$("#hittestdemo2")[0].onclick = function (e) {
				var x, y;
				x = e.offsetX;
				y = e.offsetY;

				if ( ctx.isPointInPath(x, y) ) {
					alert( "hit event ("+x+","+y+")" );
				}
			}
			$("#hittestdemo2")[0].onmousemove = function (e) {
				var x, y;
				x = e.offsetX;
				y = e.offsetY;
				$("#hitpos").text("("+x+","+y+")");
				//console.log( x+','+y);
			}
		}
		hitTest();
		

Event

		function aminoTest() {
			var amino = new Amino();
			var can = amino.addCanvas('hittestdemo3');
			can.setBackground("white");
			var all = new Group();
			can.add(all);

			//add circle w/ event listener
			var cir = new Circle();
			cir.set(300,150,30);
			cir.setFill("red");
			all.add(cir);
			can.onPress(cir,function() {
				if(cir.getFill() == "red") {
					cir.setFill("blue");
					var anim = new PropAnim(trans,"translateX",-250,100,1);
					amino.addAnim(anim);
					anim.start();
					//anim.setTween(EASE_OUT);
				} else {
					cir.setFill("red");
					var anim = new PropAnim(trans,"rotate",0,360,0.5);
					//anim.setTween(EASE_OUT_OVER);
					amino.addAnim(anim);
					anim.start();
				}
			});

			//add text inside trasnform
			var text = new Text()
				.setText("Amino!")
				.setFill("#50c0e0")
				.setY(100)
				.setFont("bold 50pt Arial")
				;
			var trans = new Transform(text);
			trans.setTranslateX(100);
			all.add(trans);
		};
		aminoTest();
		

reference - http://goamino.org/

Animation

Animation

setInterval

Animation

requestAnimationFrame

Animation

requestAnimationFrame

 
    // shim layer with setTimeout fallback
    window.requestAnimFrame = (function(){
      return  window.requestAnimationFrame     || 
              window.webkitRequestAnimationFrame || 
              window.mozRequestAnimationFrame    || 
              window.oRequestAnimationFrame      || 
              window.msRequestAnimationFrame     || 
              function( callback ){
                window.setTimeout(callback, 1000 / 60);
              };
    })();
 
 
    // usage: 
    // instead of setInterval(render, 16) ....
 
    (function animloop(){
      requestAnimFrame(animloop);
      render();
    })();
    // place the rAF *before* the render() to assure as close to 
    // 60fps with the setTimeout fallback.

Simple Animation

		window.requestAnimFrame = (function(){
			return  window.requestAnimationFrame || 
              window.webkitRequestAnimationFrame || 
              window.mozRequestAnimationFrame    || 
              window.oRequestAnimationFrame      || 
              window.msRequestAnimationFrame     || 
              function( callback ){
                window.setTimeout(callback, 1000 / 60);
              };
		})();

		var x = 0;
		function drawIt() {
			window.requestAnimFrame(drawIt);
			var canvas = document.getElementById('anidemo1');
			var c = canvas.getContext('2d');
			c.clearRect(0,0,canvas.width,canvas.height);
			c.fillStyle = 'white';
			c.fillRect(0,0,350,200);
			c.fillStyle = "red";
			c.fillRect(x,100,200,100);
			x+=5;
		}
		function simpleAniStart() {
			window.requestAnimFrame(drawIt);
		}
		

Particle Simulator

  • goal - snow animation
  • 		window.requestAnimFrame = (function(){
    			return  window.requestAnimationFrame || 
                  window.webkitRequestAnimationFrame || 
                  window.mozRequestAnimationFrame    || 
                  window.oRequestAnimationFrame      || 
                  window.msRequestAnimationFrame     || 
                  function( callback ){
                    window.setTimeout(callback, 1000 / 60);
                  };
    		})();
    
    		var canvas = document.getElementById('canvas');
    		var particles = [];
    		var tick = 0;
    		function loop() {
    		    window.requestAnimFrame(loop);
    
    			// implement the classic particle simulator algorithm
    		    createParticles();
    		    updateParticles();
    		    killParticles();
    		    drawParticles();
    		}
    		window.requestAnimFrame(loop);
    		

    Particle Simulator

    createParticles

    		function createParticles() {
    		    //check on every 10th tick check
    			if(tick % 10 == 0) {
    				if(particles.length < 100) {
    					particles.push({
    					    x: Math.random()*canvas.width,
    						y: 0,
    	                    speed: 2+Math.random()*3, //between 2 and 5
    		                radius: 5+Math.random()*5, //between 5 and 10
    			            color: "white",
    					});
    				}
    			}
    		}
    		

    Particle Simulator

    updateParticles

    		function updateParticles() {
    		    for(var i in particles) {
    				var part = particles[i];
    			    part.y += part.speed;
    		    }
    		}
    		

    Particle Simulator

    drawParticles

    		function drawParticles() {
    		    var c = canvas.getContext('2d');
    		    c.fillStyle = "black";
    		    c.fillRect(0,0,canvas.width,canvas.height);
    		    for(var i in particles) {
    		        var part = particles[i];
    				c.beginPath();
    		        c.arc(part.x,part.y, part.radius, 0, Math.PI*2);
    		        c.closePath();
    				c.fillStyle = part.color;
    		        c.fill();
    		    }
    		}
    		

    Particle Simulator

    killParticles

    		function killParticles() {
    			for(var i in particles) {
    				var part = particles[i];
    		        if(part.y > canvas.height) {
    				    part.y = 0;
    		        }
    		    }
    		}
    		

    What is a Sprite?

    Why and When to use Sprites?

    Sprites are good for a few of things.

    1. sprite is an image so it will probably draw faster than vectors, especially if those are complicated vectors.
    2. sprites are great for when you need to draw the same thing over and over.
    3. sprites are fast to download and draw as part of a sheet.
    4. uses less memory to have one large image than a bunch of smaller ones.
    5. easy collaboration. artist could easily update the graphics and animation without touching the code.

    Sprite Animation

    		window.requestAnimFrame = (function(){
    			return  window.requestAnimationFrame || 
    		      window.webkitRequestAnimationFrame || 
    			  window.mozRequestAnimationFrame    || 
    		      window.oRequestAnimationFrame      || 
    		      window.msRequestAnimationFrame     || 
    		      function( callback ){
    		        window.setTimeout(callback, 1000 / 60);
    		      };
    		})();
    		var tick = 0;
    		var y = 0;
    		var move = -128;
    		var smurfimg = new Image();
    		smurfimg.src = "./images/smurfsprite.png";
    		var smurfcanvas;
    		var smurfctx;
    
            var runAnimation = {
              value: false,
    		  isFirst: true
            };
    
    		function loop() {
    		    window.requestAnimFrame(loop);
     
    		    // draw logic
    			if ( runAnimation.value ) {
    				initSmurfCanvas();
    				smurfctx.save();
    
    				var frameX = tick % 4;
    				var x = frameX * 128;
    				if ( tick === 0) {
    					y=0;
    				} else if ( tick === 4 ) {
    					y=128;
    				} else if ( tick === 8) {
    					y=256;
    				} else if ( tick === 12) {
    					y=384;
    				}
    
    				smurfctx.drawImage(
    					smurfimg,        // the image of the sprite sheet
    					x,y,128,128,  // source coordinates      (x,y,w,h)
    					move,0,128,128   // destination coordinates (x,y,w,h)
    				);
    
    				tick++;
    				if ( tick == 16 ) {
    					tick = 0;
    				}
    				move++;
    				if ( move > 300)
    				{
    					move=-128;
    				}
    				smurfctx.restore();
    			}
    		}
    		function runSmurf() {
    			runAnimation.value = !runAnimation.value;
    			if ( runAnimation.value ) {
    				$("#smurfanibt").text("Smurf Stop");
    				if ( runAnimation.isFirst ) {
    					window.requestAnimFrame(loop);
    					runAnimation.isFirst = !runAnimation.isFirst;
    				}
    			} else {
    				$("#smurfanibt").text("Smurf Run");
    			}
    		}
    
    		function initSmurfCanvas() {
    			smurfcanvas = document.getElementById('smurfani');
    			smurfctx = smurfcanvas.getContext('2d');
    			smurfctx.clearRect(0,0,canvas.width,canvas.height);
    			smurfctx.fillStyle = "white";
    		    smurfctx.fillRect(0,0,canvas.width,canvas.height);
    		}
    		initSmurfCanvas();
    		

    What is Next

    1. Making a Game
    2. 3D Graphics with WebGL and ThreeJS
    3. WebGL Hands On with ThreeJS: 3D Car
    4. WebCam Access with getUserMedia()

    Q&A

    refenrece

    /

    #