Spirograph

Assignment 5

by ClarenceDowns

HTML

<h1>Spirograph generator</h1>

<canvas id="canvas" width="400" height="400"></canvas>
<div class="main">
  <form action="#">
    <div>
      <input type="text" value="100" />
      <label for="resolution">Resolution</label>
      <input type="range" min="1" max="5000" id="resolution" value="100" />
    </div>

    <div>
      <input type="text" value="100" />
      <label for="outer">Inner</label>
      <input type="range" min="1" max="400" id="outer" value="100" />
    </div>

    <div>
      <input type="text" value="40" />
      <label for="inner">Outer</label>
      <input type="range" min="1" max="400" id="inner" value="40" />
    </div>

    <div>
      <input type="text" value="19" />
      <label for="evolution">Evolution</label>
      <input type="range" min="1" max="200" id="evolution" value="19" />
    </div>

    <div class="button-div">
      <button>Go!</button>
    </div>

  </form>

</div>

<div class="description">
  <h2>How to use it</h2>
  <p>The resolution sets the amount of divisions the script uses to plot the path. The higher it goes, the smoother the curves.</p>

  <p>The inner and outer perhaps aren't perfectly named, but broadly they are the sizes of the two circles used to trace the line.</p>

  <p>If the evolution is set to 10 (in the script changed to 1) then the spirograph will create a perfect circle. Anything else will 'evolve' the pattern.</p>

</div>

CSS

@import "compass/css3";

body {
  padding: 1em;
  background: #3498db;
  color: #fff;
  width: 710px;
  margin: 0 auto;
}

.main {
  overflow: hidden;
}

canvas {
  display: block;
  width: 400px;
  margin-right: 1em;
  border: 1px solid darken(#3498db, 20%);
  background: #fefefe;
  float: left;
}

form {
  float: right;
  width: 300px;
}

form div {
  background: lighten(#3498db, 20%);
  border: 1px solid darken(#3498db, 20%);
  padding: 1em 1em 0.6em;
  margin: 0 1em 1em;
}

form div input[type=text] {
  float: right;
  width: 80px;
  text-align: right;
  display: block;
  padding: 0.2em 0.1em 0.1em;
  margin-top: 0.2em;
  border: 1px solid darken(#3498db, 20%);
}

.button-div {
  text-align: center;
}

button {
  padding: 0.2em 2em;
  margin: 0 auto;
  border: 1px solid darken(#3498db, 40%);
  background: darken(#3498db, 20%);
  color: #fff;
}

label {
  display: block;
}

canvas,
form div {
  box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.2);
}

h1,
h2 {
  text-shadow: 0 0 6px rgba(0, 0, 0, 0.6);
}

JavaScript

c_width = 400;
c_height = 400;
c_color = "#196090";

var ctx = document.getElementById('canvas').getContext('2d');

function draw() {

  ctx.clearRect(0, 0, c_width, c_height);

  outer_size = $("#outer").val();
  inner_size = $("#inner").val();

  resolution = $("#resolution").val();
  evolution = $("#evolution").val() / 10;





  ctx.lineWidth = "1";
  ctx.strokeStyle = c_color; // Green path

  ctx.beginPath();


  // This is the part that actually does the drawing
  for (i = 0; i < resolution + 1; i++) {
    // Get the reference point from where we will draw our other circles
    j = (i / resolution) * (2 * Math.PI);
    inner_xpos = c_width / 2 + (inner_size * Math.sin(j));
    inner_ypos = c_height / 2 + (inner_size * Math.cos(j));

    // If this is left as 1, then it just draws a wider circle 
    k = j * evolution;
    outer_xpos = inner_xpos + (outer_size * Math.sin(k));
    outer_ypos = inner_ypos + (outer_size * Math.cos(k));

    ctx.lineTo(outer_xpos, outer_ypos);

  }
  ctx.stroke();

}

$('button').click(function() {
  draw();
  return false;
});

$(document).ready(function() {

  draw();

  $("input[type='range']").change(function() {
    $(this).parent().find('input:text').val($(this).val());
  });


  $("input[type='text']").change(function() {
    $(this).parent().find('input[type="range"]').val($(this).val());
  });

});