Canvas context
The canvas element is part of HTML5 and allows for dynamic, scriptable rendering of shapes and images. The actual drawing happens within a context. In this example we'll use 2d context for drawing:
var canvas = document.createElement('canvas'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; var ctx = canvas.getContext('2d'); document.body.appendChild(canvas);
Drawing shapes and lines
In order to make the changes to the context as easy as possible the best practice is to save the context before doing any changes and restoring it after we are done with drawing. Especially if we change context rotation, colors and fill styles:
ctx.save(); ... ctx.restore();
The crossroad canvas example uses these constructs for drawing shapes:
- arc
- fillRect
- moveTo + lineTo
Circle
There's no method named circle, instead we use arc and make one from 0 to 2 * Pi:
ctx.fillStyle = 'red'; ctx.beginPath(); ctx.arc(x, y, radius, startAngle, endAngle, antiClockwise); // ctx.stroke() would draw circumference, fill makes a circle ctx.fill();
Rectangle
Drawing rectangles is pretty straight forward. One must set coordinates, width and height:
ctx.fillRect (x, y, width, height);
Lines
When working with lines we can move starting point and then make a line to some other position:
ctx.beginPath(); ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.closePath(); ctx.stroke();
Clearing the drawing
Very important when doing animations because calculating what pixels to clear every time would be pretty complicated to code. Changing a small piece of canvas takes less time than clearing everything and then drawing it again. In the past developers kept an off screen canvas and did drawing on it and then at the end of the animation loop they copied the off screen canvas to the on screen canvas.
Most of the browser vendors started to do this automatically so in modern browsers keeping an off screen canvas actually degrades performance.
ctx.clearRect (x, y, width, height);
Collision detection
All objects in the crossroad animation are represented as circles. The formula for collision detection between two circles is:
function collision(c1, c2) { var dx = c1.x - c2.x; var dy = c1.y - c2.y; var dist = c1.radius + c2.radius; return (dx * dx + dy * dy <= dist * dist); }If the movement happens along a single axis line it's even simpler we just need to check the coordinate on the relevant axis (in this case x):
Math.abs(x1 - x2) > (radius + safety_distance)
requestAnimationFrame
The browser vendors optimized the usual timer animation loop and provided api for it. But since some vendors don't support it or the users have older browsers we use this pattern:
// shim layer with setTimeout fallback window.requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function( callback ){ window.setTimeout(callback, 1000 / 60); }; })(); (function animloop(){ requestAnimFrame(animloop); // call drawing functions here })();
requestAnimationFrame
And here's my example on:
CSSDeck
Codepen
GitHub
No comments:
Post a Comment