JSFiddle - React, Tailwind, and code Playground

HTML

<div class="gear paused">
    <div class="inner-gear blue">
    </div>
    <div class="inner-gear yellow">
        <div class="left-top corner"></div>
        <div class="right-top corner"></div>
        <div class="right-bottom corner"></div>
        <div class="left-bottom corner"></div>
    </div>
    <div class="inner-gear red">
    </div>
    <div class="inner-gear green">
    </div>
</div>

<div class="gear-small paused">
    <div class="inner-gear yellow">
        <div class="left-top corner"></div>
        <div class="right-top corner"></div>
        <div class="right-bottom corner"></div>
        <div class="left-bottom corner"></div>
    </div>
    <div class="inner-gear red">
    </div>
    <div class="inner-gear green">
    </div>
    <div class="inner-gear blue">
    </div>
</div>

<div id="result"></div>
<div id="variables"></div>


<div id="bgo" class="gbtn">Go</div>
<div id="bstop" class="gbtn">Stop</div>
<div id="bstep" class="gbtn">Step</div>

CSS

.gear{
    position: absolute;
    top: 100px;
    left: 100px;
    width: 200px;
    height: 200px;
    overflow: hidden;
}

.gear-small {
  position: absolute;
  top: 150px;
  left: 150px;
  width: 100px;
  height: 100px;
  overflow: hidden;
}

.inner-gear {
    width: 50%;
    float: left;
    height: 50%;
    display: inline-block;
    position: relative;
}

.corner {
    width: 1px;
    height: 1px;
    position: absolute;
    background-color: black;
    visibility: hidden;
}

.left-top { left: 0; top: 0; }
.right-top { right: 0; top: 0; }
.right-bottom { right: 0; bottom: 0; }
.left-bottom { left: 0; bottom: 0; }

.paused {
   -ms-animation-play-state: paused;
   -o-animation-play-state: paused;
   -moz-animation-play-state: paused;
   -webkit-animation-play-state: paused;
   animation-play-state: paused;
}

.red {
    background-color: red;
    opacity: 0.2;
}

.blue {
    background-color: blue;
    opacity: 0.2;    
}

.yellow {
    background-color: yellow;
}

.green {
    background-color: green;
    opacity: 0.2;
}

#result {
    color:black;
}

.gear-small {
    -webkit-animation-name: spin;
    -webkit-animation-duration: 6000ms;
    -webkit-animation-iteration-count: infinite;
    -webkit-animation-timing-function: linear;
    -moz-animation-name: spin;
    -moz-animation-duration: 6000ms;
    -moz-animation-iteration-count: infinite;
    -moz-animation-timing-function: linear;
    -ms-animation-name: spin;
    -ms-animation-duration: 6000ms;
    -ms-animation-iteration-count: infinite;
    -ms-animation-timing-function: linear;
    animation-name: spin;
    animation-duration: 6000ms;
    animation-iteration-count: infinite;
}

.gear {
    -webkit-animation-name: spin;
    -webkit-animation-duration: 4000ms;
    -webkit-animation-iteration-count: infinite;
    -webkit-animation-timing-function: linear;
    -moz-animation-name: spin;
    -moz-animation-duration: 4000ms;
    -moz-animation-iteration-count: infinite;
   ...

JavaScript

var degree = 0;
var degreeSmall = 0;
var timer=30;
var $spin = $(".gear");
var $spinSmall = $(".gear-small");
var to;
var toSmall;
var stopped;

function isUndefined(a) {
    return a === undefined;
}

/**
 * Helper function to determine whether there is an intersection between the two polygons described
 * by the lists of vertices. Uses the Separating Axis Theorem
 *
 * @param a an array of connected points [{x:, y:}, {x:, y:},...] that form a closed polygon
 * @param b an array of connected points [{x:, y:}, {x:, y:},...] that form a closed polygon
 * @return true if there is any intersection between the 2 polygons, false otherwise
 */
function doPolygonsIntersect(a, b) {
    var polygons = [a, b];
    var minA, maxA, projected, i, i1, j, minB, maxB;

    for (i = 0; i < polygons.length; i++) {

        // for each polygon, look at each edge of the polygon, and determine if it separates
        // the two shapes
        var polygon = polygons[i];
        for (i1 = 0; i1 < polygon.length; i1++) {

            // grab 2 vertices to create an edge
            var i2 = (i1 + 1) % polygon.length;
            var p1 = polygon[i1];
            var p2 = polygon[i2];

            // find the line perpendicular to this edge
            var normal = { x: p2.y - p1.y, y: p1.x - p2.x };

            minA = maxA = undefined;
            // for each vertex in the first shape, project it onto the line perpendicular to the edge
            // and keep track of the min and max of these values
            for (j = 0; j < a.length; j++) {
                projected = normal.x * a[j].x + normal.y * a[j].y;
                if (isUndefined(minA) || projected < minA) {
                    minA = projected;
                }
                if (isUndefined(maxA) || projected > maxA) {
                    maxA = projected;
                }
            }

            // for each vertex in the second shape, project it onto the line perpendicular to the edge
            // and keep track...