HTML Canvas Animation mechanical gears
<!DOCTYPE HTML> <html> <head> <script> var Animation = function(canvasId) { this.canvas = document.getElementById(canvasId); this.context = this.canvas.getContext("2d"); this.t = 0;//from w w w. j av a 2s . c o m this.timeInterval = 0; this.startTime = 0; this.lastTime = 0; this.frame = 0; this.animating = false; // provided by Paul Irish window.requestAnimFrame = (function(callback) { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60); }; })(); }; Animation.prototype.getContext = function() { return this.context; }; Animation.prototype.getCanvas = function() { return this.canvas; }; Animation.prototype.clear = function() { this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); }; Animation.prototype.setDrawStage = function(func) { this.drawStage = func; }; Animation.prototype.getFrame = function() { return this.frame; }; Animation.prototype.start = function() { this.animating = true; var date = new Date(); this.startTime = date.getTime(); this.lastTime = this.startTime; if (this.drawStage !== undefined) { this.drawStage(); } this.animationLoop(); }; Animation.prototype.stop = function() { this.animating = false; }; Animation.prototype.getTimeInterval = function() { return this.timeInterval; }; Animation.prototype.getTime = function() { return this.t; }; Animation.prototype.animationLoop = function() { var that = this; this.frame++; var date = new Date(); var thisTime = date.getTime(); this.timeInterval = thisTime - this.lastTime; this.t += this.timeInterval; this.lastTime = thisTime; if (this.drawStage !== undefined) { this.drawStage(); } if (this.animating) { requestAnimFrame(function() { that.animationLoop(); }); } }; function Gear(config){ this.x = config.x; this.y = config.y; this.outerRadius = config.outerRadius; this.innerRadius = config.innerRadius; this.holeRadius = config.holeRadius; this.numTeeth = config.numTeeth; this.theta = config.theta; this.thetaSpeed = config.thetaSpeed; this.lightColor = config.lightColor; this.darkColor = config.darkColor; this.clockwise = config.clockwise; this.midRadius = config.outerRadius - 10; } Gear.prototype.draw = function(context){ context.save(); context.translate(this.x, this.y); context.rotate(this.theta); // draw gear teeth context.beginPath(); context.lineJoin = "bevel"; // loop through the number of points to create the gear shape var numPoints = this.numTeeth * 2; for (var n = 0; n < numPoints; n++) { var radius = null; if (n % 2 == 0) { radius = this.outerRadius; } else { radius = this.innerRadius; } var theta = ((Math.PI * 2) / numPoints) * (n + 1); var x = (radius * Math.sin(theta)); var y = (radius * Math.cos(theta)); if (n == 0) { context.moveTo(x, y); } // if any other iteration, use lineTo() to connect sub paths else { context.lineTo(x, y); } } context.closePath(); // define the line width and stroke color context.lineWidth = 5; context.strokeStyle = this.darkColor; context.stroke(); // draw gear body context.beginPath(); context.arc(0, 0, this.midRadius, 0, 2 * Math.PI, false); // create a linear gradient var grd = context.createLinearGradient(-1 * this.outerRadius / 2, -1 * this.outerRadius / 2, this.outerRadius / 2, this.outerRadius / 2); grd.addColorStop(0, this.lightColor); grd.addColorStop(1, this.darkColor); context.fillStyle = grd; context.fill(); context.lineWidth = 5; context.strokeStyle = this.darkColor; context.stroke(); // draw gear hole context.beginPath(); context.arc(0, 0, this.holeRadius, 0, 2 * Math.PI, false); context.fillStyle = "white"; context.fill(); context.strokeStyle = this.darkColor; context.stroke(); context.restore(); }; window.onload = function(){ var anim = new Animation("myCanvas"); var canvas = anim.getCanvas(); var context = anim.getContext(); var gears = []; // add blue gear gears.push(new Gear({ x: 270, y: 105, outerRadius: 90, innerRadius: 50, holeRadius: 10, numTeeth: 24, theta: 0, thetaSpeed: 1 / 1000, lightColor: "yellow", darkColor: "pink", clockwise: false })); // add red gear gears.push(new Gear({ x: 372, y: 190, outerRadius: 50, innerRadius: 15, holeRadius: 10, numTeeth: 12, theta: 0.14, thetaSpeed: 2 / 1000, lightColor: "red", darkColor: "blue", clockwise: true })); anim.setDrawStage(function(){ // update for (var i = 0; i < gears.length; i++) { var gear = gears[i]; var thetaIncrement = gear.thetaSpeed * this.getTimeInterval(); gear.theta += gear.clockwise ? thetaIncrement : -1 * thetaIncrement; } // clear this.clear(); // draw for (var i = 0; i < gears.length; i++) { gears[i].draw(context); } }); anim.start(); }; </script> </head> <body> <canvas id="myCanvas" width="600" height="350" style="border: 1px solid black;"> </canvas> </body> </html>