JSFiddle - React, Tailwind, and code Playground

by jacomyal

HTML

<div id="range-container">
    <input id="range" type="range" value="15" max="1000" min="10" step="5" />
</div>
<div id="container">
    <canvas id="stage"></canvas>
</div>

CSS

body {
    margin: 0;
    padding: 0;
    background: #ccc;
}
#container {
    position: absolute;
    top: 50px;
    left: 10px;
    right: 10px;
    bottom: 10px;
}
#stage {
    background: #fff;
}
#range-container {
    position: absolute;
    top: 10px;
    left: 10px;
    right: 10px;
    height: 30px;
}
#range {
    width: 100%;
}

JavaScript

/**
 * This fiddle is just a quick test to arrange
 * N elements on a disc. This spiral based solution
 * is inspired by this block:
 *   http://bl.ocks.org/fabiovalse/dfcd8104a79aed092af1
 */

var container = document.getElementById('container'),
    canvas = document.getElementById('stage'),
    ctx = canvas.getContext('2d'),
    N = 10; // last number of drawn circles

function render(n) {
    N = (n = n || N)
    
    canvas.width = canvas.width;

    var w = canvas.offsetWidth,
        h = canvas.offsetHeight;
    
    ctx.translate(w / 2, h / 2);

    var i = 0,
        awayStep = 3,
        chord = 20;

    for (theta = 2; i < n; i++) {
        away = awayStep * theta;
        theta += chord / away;
      
        renderOneCircle(
            Math.cos(theta) * away,
            Math.sin(theta) * away,
            5 - (4 * i / N)
        );
    }
}

function renderOneCircle(x, y, size) {
    ctx.fillStyle = '#666';
    ctx.beginPath();
    ctx.arc(x, y, size, 0, 2 * Math.PI, false);
    ctx.closePath();
    ctx.fill();
}

// Listen to range change:
document.getElementById('range').addEventListener('input', function(e) {
    render(+e.target.value);
});

// Deal with resize and initial rendering:
function resize() {
    var w = container.offsetWidth,
        h = container.offsetHeight;
    
    canvas.style.width = w + 'px';
    canvas.style.height = h + 'px';
    canvas.setAttribute('width', w + 'px');
    canvas.setAttribute('height', h + 'px');
    
    render();
}
window.addEventListener('resize', resize);
resize();