1var IS_SKV8 = typeof document == "undefined"; 2var HAS_PATH = typeof Path2D != "undefined"; 3var HAS_DISPLAY_LIST = typeof DisplayList != "undefined"; 4 5var NumTeeth = 24; 6var NumGears = 60; 7var DeltaTheta = Math.PI/90; 8var FaceColors = ["#000099", "#006600", "#990000", "#EEEE00"]; 9var SideColors = ["#0000FF", "#009900", "#FF0000", "#CCCC00"]; 10 11function makeGear(pathLike, r) { 12 var dT = Math.PI*2/NumTeeth; 13 var dTq = dT/4; 14 var outer = r; 15 var inner = 0.7 * r; 16 pathLike.moveTo(Math.sin(-2*dTq)*outer, Math.cos(-2*dTq)*outer); 17 for (var i=0; i<NumTeeth; i+=2) { 18 pathLike.lineTo(Math.sin(dT*i-dTq)*outer, Math.cos(dT*i-dTq)*outer); 19 pathLike.lineTo(Math.sin(dT*i+dTq)*inner, Math.cos(dT*i+dTq)*inner); 20 pathLike.lineTo(Math.sin(dT*(i+1)-dTq)*inner, Math.cos(dT*(i+1)-dTq)*inner); 21 pathLike.lineTo(Math.sin(dT*(i+1)+dTq)*outer, Math.cos(dT*(i+1)+dTq)*outer); 22 } 23} 24 25function gearPath(r) { 26 if (HAS_PATH) { 27 p = new Path2D(); 28 makeGear(p, r) 29 p.closePath(); 30 return p; 31 } else { 32 return null; 33 } 34} 35 36function gearDisplayListStroke(r, color) { 37 if (HAS_DISPLAY_LIST) { 38 p = new Path2D(); 39 makeGear(p, r) 40 p.closePath(); 41 var dl = new DisplayList(); 42 dl.strokeStyle = color; 43 dl.stroke(p); 44 dl.finalize() 45 return dl; 46 } else { 47 return null; 48 } 49} 50 51function gearDisplayListFill(r, color) { 52 if (HAS_DISPLAY_LIST) { 53 p = new Path2D(); 54 makeGear(p, r) 55 p.closePath(); 56 var dl = new DisplayList(); 57 dl.fillStyle = color; 58 dl.fill(p); 59 dl.finalize() 60 return dl; 61 } else { 62 return null; 63 } 64} 65 66function strokeGear(ctx, gear) { 67 if (HAS_PATH) { 68 ctx.stroke(gear.path); 69 } else { 70 ctx.beginPath(); 71 makeGear(ctx, gear.r); 72 ctx.closePath(); 73 ctx.stroke(); 74 } 75} 76 77function fillGear(ctx) { 78 if (HAS_PATH) { 79 ctx.fill(gear.path); 80 } else { 81 ctx.beginPath(); 82 makeGear(ctx, gear.r); 83 ctx.closePath(); 84 ctx.fill(); 85 } 86} 87 88function draw3DGear(ctx, angle, gear) { 89 ctx.strokeStyle = gear.sideColor; 90 ctx.fillStyle = gear.faceColor; 91 ctx.rotate(angle); 92 strokeGear(ctx, gear); 93 for (var i=0; i < 20; i++) { 94 ctx.rotate(-angle); 95 ctx.translate(0.707, 0.707); 96 ctx.rotate(angle); 97 if (HAS_DISPLAY_LIST) { 98 ctx.draw(gear.gearStroke); 99 } else { 100 strokeGear(ctx, gear); 101 } 102 } 103 if (HAS_DISPLAY_LIST) { 104 ctx.draw(gear.gearFill); 105 } else { 106 fillGear(ctx, gear); 107 } 108 ctx.rotate(-angle); 109} 110 111function draw3DGearAt(ctx, angle, gear) { 112 ctx.save(); 113 ctx.translate(gear.x, gear.y); 114 draw3DGear(ctx, angle, gear); 115 ctx.restore(); 116} 117 118var onDraw = function() { 119 var ticks=0; 120 var rotation = 0; 121 var gears = []; 122 123 for (var i=0; i<NumGears; i++) { 124 color = Math.floor(Math.random()*FaceColors.length); 125 r = Math.random()*100+5; 126 gears.push({ 127 x: Math.random()*500, 128 y: Math.random()*500, 129 path: gearPath(r), 130 gearFill: gearDisplayListFill(r, FaceColors[color]), 131 gearStroke: gearDisplayListStroke(r, SideColors[color]), 132 r: r, 133 faceColor: FaceColors[color], 134 sideColor: SideColors[color] 135 }); 136 } 137 138 function draw(ctx) { 139 ctx.resetTransform(); 140 141 ctx.fillStyle = "#FFFFFF"; 142 ctx.fillRect(0, 0, 499, 499); 143 144 rotation += DeltaTheta; 145 if (rotation >= Math.PI*2) { 146 rotation = 0; 147 } 148 149 for (var i=0; i < gears.length; i++) { 150 gear = gears[i]; 151 draw3DGearAt(ctx, rotation, gear); 152 } 153 154 ticks++; 155 if (IS_SKV8) { 156 inval(); 157 } 158 }; 159 160 function fps() { 161 console.log(ticks); 162 ticks = 0; 163 setTimeout(fps, 1000); 164 }; 165 166 setTimeout(fps, 1000); 167 168 return draw; 169}(); 170 171if (!IS_SKV8) { 172 window.onload = function(){ 173 var canvas = document.getElementById("gears"); 174 var ctx = canvas.getContext("2d"); 175 function drawCallback() { 176 onDraw(ctx); 177 setTimeout(drawCallback, 1); 178 } 179 setTimeout(drawCallback, 1); 180 } 181} 182 183console.log("HAS_PATH: " + HAS_PATH); 184