JSFiddle - React, Tailwind, and code Playground

by Alex Jones

HTML

<div class="circle" id="smcircle"></div>

CSS

body {
    -webkit-transform: translateZ(0.0);
}

.circle {
    border-radius: 10px;
    width: 20px;
    height: 20px;
    background-color: red;
    position: absolute;
}

.small-circle {
    border-radius: 1px;
    width: 2px;
    height: 2px;
    background-color: blue;
    position: absolute;
}

.anim-path {
    -webkit-animation: followPath 5000ms;
}

JavaScript

function addCircleAt(x, y, container) {
    var div = document.createElement("div");
    div.classList.add("small-circle");
    container.appendChild(div);
    div.style["left"] = x + "px";
    div.style["top"] = y + "px";
}

function createPathAnimation (points) {
    var style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = '@-webkit-keyframes followPath {';
    var keys = Object.keys(points);
    var len = keys.length;
    var keyframeStep = 100 / len;
    var step = 0;
    
    keys.forEach(function(key) {
        el = points[key];
        style.innerHTML += (
            (step.toFixed(2)) + 
            "% { left:" + (Number(key).toFixed(2)) + "px;" + 
            "top:" + (+el.toFixed(2)) + "px;" + "}"
        );
        step += keyframeStep;
    });
    style.innerHTML += "};"
    document.head.appendChild(style);
}

(function() {
    var startX = 0;
    var endX = 300;
    var stepX = 1;
    var scaleY = 50;
    var offsetY = 100;
    var stretch = 0.5;
    out = []
    for(var i = startX; i <= endX; i+= stepX) {
        y = Math.sin(stretch*i/(2*Math.PI));
        out[i] = offsetY + y*scaleY;
    }
    createPathAnimation(out);
    var smcirc = document.querySelector("#smcircle");
    smcirc.classList.add("anim-path");
}());