| var IS_SKV8 = typeof document == "undefined"; |
| var HAS_PATH = typeof Path2D != "undefined"; |
| var HAS_DISPLAY_LIST = typeof DisplayList != "undefined"; |
| |
| var NumTeeth = 24; |
| var NumGears = 60; |
| var DeltaTheta = Math.PI/90; |
| var FaceColors = ["#000099", "#006600", "#990000", "#EEEE00"]; |
| var SideColors = ["#0000FF", "#009900", "#FF0000", "#CCCC00"]; |
| |
| function makeGear(pathLike, r) { |
| var dT = Math.PI*2/NumTeeth; |
| var dTq = dT/4; |
| var outer = r; |
| var inner = 0.7 * r; |
| pathLike.moveTo(Math.sin(-2*dTq)*outer, Math.cos(-2*dTq)*outer); |
| for (var i=0; i<NumTeeth; i+=2) { |
| pathLike.lineTo(Math.sin(dT*i-dTq)*outer, Math.cos(dT*i-dTq)*outer); |
| pathLike.lineTo(Math.sin(dT*i+dTq)*inner, Math.cos(dT*i+dTq)*inner); |
| pathLike.lineTo(Math.sin(dT*(i+1)-dTq)*inner, Math.cos(dT*(i+1)-dTq)*inner); |
| pathLike.lineTo(Math.sin(dT*(i+1)+dTq)*outer, Math.cos(dT*(i+1)+dTq)*outer); |
| } |
| } |
| |
| function gearPath(r) { |
| if (HAS_PATH) { |
| p = new Path2D(); |
| makeGear(p, r) |
| p.closePath(); |
| return p; |
| } else { |
| return null; |
| } |
| } |
| |
| function gearDisplayListStroke(r, color) { |
| if (HAS_DISPLAY_LIST) { |
| p = new Path2D(); |
| makeGear(p, r) |
| p.closePath(); |
| var dl = new DisplayList(); |
| dl.strokeStyle = color; |
| dl.stroke(p); |
| dl.finalize() |
| return dl; |
| } else { |
| return null; |
| } |
| } |
| |
| function gearDisplayListFill(r, color) { |
| if (HAS_DISPLAY_LIST) { |
| p = new Path2D(); |
| makeGear(p, r) |
| p.closePath(); |
| var dl = new DisplayList(); |
| dl.fillStyle = color; |
| dl.fill(p); |
| dl.finalize() |
| return dl; |
| } else { |
| return null; |
| } |
| } |
| |
| function strokeGear(ctx, gear) { |
| if (HAS_PATH) { |
| ctx.stroke(gear.path); |
| } else { |
| ctx.beginPath(); |
| makeGear(ctx, gear.r); |
| ctx.closePath(); |
| ctx.stroke(); |
| } |
| } |
| |
| function fillGear(ctx) { |
| if (HAS_PATH) { |
| ctx.fill(gear.path); |
| } else { |
| ctx.beginPath(); |
| makeGear(ctx, gear.r); |
| ctx.closePath(); |
| ctx.fill(); |
| } |
| } |
| |
| function draw3DGear(ctx, angle, gear) { |
| ctx.strokeStyle = gear.sideColor; |
| ctx.fillStyle = gear.faceColor; |
| ctx.rotate(angle); |
| strokeGear(ctx, gear); |
| for (var i=0; i < 20; i++) { |
| ctx.rotate(-angle); |
| ctx.translate(0.707, 0.707); |
| ctx.rotate(angle); |
| if (HAS_DISPLAY_LIST) { |
| ctx.draw(gear.gearStroke); |
| } else { |
| strokeGear(ctx, gear); |
| } |
| } |
| if (HAS_DISPLAY_LIST) { |
| ctx.draw(gear.gearFill); |
| } else { |
| fillGear(ctx, gear); |
| } |
| ctx.rotate(-angle); |
| } |
| |
| function draw3DGearAt(ctx, angle, gear) { |
| ctx.save(); |
| ctx.translate(gear.x, gear.y); |
| draw3DGear(ctx, angle, gear); |
| ctx.restore(); |
| } |
| |
| var onDraw = function() { |
| var ticks=0; |
| var rotation = 0; |
| var gears = []; |
| |
| for (var i=0; i<NumGears; i++) { |
| color = Math.floor(Math.random()*FaceColors.length); |
| r = Math.random()*100+5; |
| gears.push({ |
| x: Math.random()*500, |
| y: Math.random()*500, |
| path: gearPath(r), |
| gearFill: gearDisplayListFill(r, FaceColors[color]), |
| gearStroke: gearDisplayListStroke(r, SideColors[color]), |
| r: r, |
| faceColor: FaceColors[color], |
| sideColor: SideColors[color] |
| }); |
| } |
| |
| function draw(ctx) { |
| ctx.resetTransform(); |
| |
| ctx.fillStyle = "#FFFFFF"; |
| ctx.fillRect(0, 0, 499, 499); |
| |
| rotation += DeltaTheta; |
| if (rotation >= Math.PI*2) { |
| rotation = 0; |
| } |
| |
| for (var i=0; i < gears.length; i++) { |
| gear = gears[i]; |
| draw3DGearAt(ctx, rotation, gear); |
| } |
| |
| ticks++; |
| if (IS_SKV8) { |
| inval(); |
| } |
| }; |
| |
| function fps() { |
| console.log(ticks); |
| ticks = 0; |
| setTimeout(fps, 1000); |
| }; |
| |
| setTimeout(fps, 1000); |
| |
| return draw; |
| }(); |
| |
| if (!IS_SKV8) { |
| window.onload = function(){ |
| var canvas = document.getElementById("gears"); |
| var ctx = canvas.getContext("2d"); |
| function drawCallback() { |
| onDraw(ctx); |
| setTimeout(drawCallback, 1); |
| } |
| setTimeout(drawCallback, 1); |
| } |
| } |
| |
| console.log("HAS_PATH: " + HAS_PATH); |