Points on a circle

by Dan Shahin

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/snap.js/1.9.2/snap.min.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/snap.js/1.9.2/snap.css">
<script src="http://cdn.jsdelivr.net/snap.svg/0.1.0/snap.svg-min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<svg id="paper" />
<br/>
<div id="slider"></div>
<label for="pattern">pattern</label>
<input min="0" class="control" value="324" id="pattern" type="number" />
<br/>
<div class="slider" id="sliderPattern"></div>
<label for="size">diameter</label>
<input max="400" class="control" value="400" id="size" type="number" />
<br/>
<div class="slider" id="sliderPattern"></div>
<div class="slider" id="sliderSize"></div>
<label for="numPoints">number of points</label>
<input min="1" max="500" class="control" value="25" id="numPoints" type="number" />
<br/>
<div class="slider" id="sliderPoints"></div>
<br/>

CSS

.slider, svg, label {
    margin:10px;
    width:400px;
}
.padded {
    padding-top: 60px;
}
/* From snap.css */
 .snap-content {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    width: auto;
    height: auto;
    z-index: 2;
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    -webkit-transform: translate3d(0, 0, 0);
    -moz-transform: translate3d(0, 0, 0);
    -ms-transform: translate3d(0, 0, 0);
    -o-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
}
.snap-drawers {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    width: auto;
    height: auto;
}
.snap-drawer {
    position: absolute;
    top: 0;
    right: auto;
    bottom: 0;
    left: auto;
    width: 265px;
    height: auto;
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    -webkit-transition: width 0.3s ease;
    -moz-transition: width 0.3s ease;
    -ms-transition: width 0.3s ease;
    -o-transition: width 0.3s ease;
    transition: width 0.3s ease;
}
.snap-drawer-left {
    left: 0;
    z-index: 1;
}
.snap-drawer-right {
    right: 0;
    z-index: 1;
}
.snapjs-left .snap-drawer-right, .snapjs-right .snap-drawer-left {
    display: none;
}
.snapjs-expand-left .snap-drawer-left, .snapjs-expand-right .snap-drawer-right {
    width: 100%;
}
#content {
    background: white;
}

JavaScript

var paper = Snap('#paper');

var height = 400,
    width = height,
    radius = (height / 2)
    pointSize = 5;

paper.attr({
    height: height,
    width: width
});

var disk = paper.circle((height / 2), (width / 2), height / 2).attr({
    fill: randColor(),
    class: 'circle'
});


spreadToppings({
    radius: 200,
    numPoints: 25,
    pattern: 323
});

$('body').on('click', '.circle', function () {
    var circle = $(this);
    circle.attr({
        fill: randColor()
    });
});

$('.control').change(function () {
    var state = {
        pattern: $('#pattern').val(),
        radius: $('#size').val() / 2,
        numPoints: $('#numPoints').val(),
    }
    spreadToppings(state);
});

$('#sliderSize').slider({
    range: "max",
    min: 0,
    max: 400,
    value: 400,
    slide: function (event, ui) {
        $('#size').val(ui.value).change();
    }
});

$('#sliderPoints').slider({
    range: "max",
    min: 1,
    max: 500,
    value: 0,
    slide: function (event, ui) {
        $('#numPoints').val(ui.value).change();
    }
});

$('#sliderPattern').slider({
    range: "max",
    min: 0,
    max: 2000,
    value: 323,
    slide: function (event, ui) {
        $('#pattern').val(ui.value).change();
    }
});

function spreadToppings(args) {

    //adapted from 
    //http://blog.marmakoide.org/?p=1

    if (!args) {
        args = {};
    }

    $('.topping').remove();

    var radius = args.radius || (height / 2),

        numPoints = args.numPoints || 20,

        pattern = args.pattern || 0,

        golden_angle = Math.PI * (3 - Math.sqrt(pattern)),

        points = [],

        span = range( numPoints);

    for (var i = 0; i < span.length; i++) {
        var v = span[i];
        var theta = v * golden_angle;

        var r = Math.sqrt(v) / Math.sqrt(numPoints);
        points.push({
            x: (r * Math.cos(theta)) * radius + (height / 2),
            y: (r * Math.sin(theta)) * radius + (width / 2)
        });
    }

    var toppingColor = 0;

  ...