Gears

HTML

<div id="ctrl">
<label for="teeth_b">Teeth O</label><input type="text" id="teeth_b" value="60"></input>
<label for="teeth_m">Teeth o</label><input type="text" id="teeth_m" value="36"></input>
<label for="teeth_s">Teeth *</label><input type="text" id="teeth_s" value="15"></input>
<label for="run_raf">AnimFrame</label>
<input type="radio" name="run_method" value="raf" id="run_raf">
<br>
<label for="tps_1">Teeth/s 1</label><input type="text" id="tps_1" value="3"></input>
<label for="teeth_w">Teeth Width</label><input type="text" id="teeth_w" value="2.6"></input>
<label for="tps_e">Teeth/s e</label><input type="text" id="tps_e" value="10" readonly="true"></input>
<label for="run_iv">Interval</label>
<input type="radio" name="run_method" value="iv" id="run_iv" checked="true">
<br>
<label for="decor">Decor</label>
<input type="range" min="0" max="4" id="decor" step="1" value="3">
<span id="decorv">1</span></input>

<label for="pin">Pin</label>
<input type="checkbox" id="pin"></input>
<label for="shadow" id="lash">Shadow</label>
<input type="checkbox" id="shadow" checked></input>
<input type="checkbox" id="shwheel"></input>
<br>
<label for="fps">Interval FPS</label>
<input type="range" min="0.5" max="160.0" id="fps" step="0.5" value="80.0">
<span id="fpsv">50.0</span></input>
<label for="spikes">Spikes</label><input type="text" id="spikes" value="6"></input>
<label for="star">Star</label>
<input type="checkbox" id="star"></input>
<br>
<br>
<!--input type="text" id="arr" value="*=Oo=O-o=*"></input-->
<input type="text" id="arr" value="*-O=*o-O"></input>
<button id="build">Build</button>
<button id="stop">Stop</button>
<button id="step">Step</button>
<button id="run">Run</button>

</div>
<canvas id="can"></canvas>

CSS

* {
    padding:0;
    margin :0;
    color: #489721;
    font: 10px Arial;
}
canvas {
    display:block;
    border: 4px double #481819;
    margin: 10px auto;
}
#ctrl {
    margin: 10px auto;
    padding: 5px;
    width : 750px;
    border: 4px double #481819;
}
label {
    margin: 2px;
    width : 85px;
    display: inline-block;
    border-bottom: 1px double #aaa;
    text-align: right
}
label, button,
input[type=range],
input[type=checkbox],
input[type=radio]
{
    cursor: pointer;
}
button {
    padding: 1px 4px;
    vertical-align: top;
}
#teeth_b,
#teeth_m,
#teeth_s,
#teeth_w,
#spikes,
#tps_1,
#tps_e
{
    width: 60px;
    text-align: right;
}
#fpsv, #decorv {
    display : inline-block;
    width   : 75px;
    font-style: italic;
}
#lash {
    margin-left: 48px;
}
input[type=text] {
    border: 1px double #aaa;
    color: #336c17;
}
#tps_e
{
    color: #990;
}
#arr {
    font-size: 12px;
};

JavaScript

/* requestAnimationFrame polyfill by Erik Möller.
 *
 * http://paulirish.com/2011/requestanimationframe-for-smart-animating/
 * http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
 * Fixes from Paul Irish and Tino Zijdel.
 * */
(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame =
                    window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame =
                    window[vendors[x]+'CancelAnimationFrame'] ||
                    window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback /*, element*/) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() {
                    callback(currTime + timeToCall);
                }, timeToCall
            );
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

var PI  = Math.PI,
    P2  = PI*2,
    cos = Math.cos,
    sin = Math.sin;

function isNumber(n) {
    return !isNaN(parseFloat(n)) && isFinite(n);
}

function isNumbers(a) {
    var i;
    for (i = 0; i < a.length; ++i)
        if (!isNumber(a[i]))
            return 0;
    return 1;
}

function CogWheels() {
    this.can    = document.getElementById('can');
    this.ctx    = this.can.getContext("2d");
    this.cm = {
        main:{can: document.createElement('CANVAS'),ok:0}
        //gear:{can: document.createElement('CANVAS'),ok:0}
    };
    this.cm.main.ctx = this.cm.main.can.getContext("2d");

    this.ofs    = {x:10, y:50};
    this.grect  = null;

    this.parts  =...