JSFiddle - React, Tailwind, and code Playground

by karthick6891

HTML

<canvas class='c'></canvas>
<canvas class='c'></canvas>
<canvas class='c'></canvas>

<section class='controls'>
  <section class='controls__basic'>
    <label for='r1'>fixed circle radius (R):</label>
    <input id='r1' type='range' 
           min='.2' max='.62' value='.5' 
           step='.01'/>

    <label for='r2'>rolling circle radius (r):</label>
    <input id='r2' type='range' 
           min='.25' max='.62' value='.18' 
           step='.01'/>

    <label for='d'>tracer distance (d):</label>
    <input id='d' type='range' 
           min='.5' max='2.62' value='1.87' 
           step='.05'/>

    <label for='v'>velocity (v):</label>
    <input id='v' type='range' 
           min='.2' max='1' value='.5' 
           step='.01'/>
  </section>

  <section class='controls__type'>
    <input type='radio' name='type' id='hypo' checked/>
    <label for='hypo'>hypotrochoid</label>
    <input type='radio' name='type' id='epi'/>
    <label for='epi'>epitrochoid</label>
  </section>

  <section class='controls__scheme'>
    <label for='hue'>hue:</label>
    <input id='hue' type='range' 
           min='0' max='360' value='90' 
           step='1'/>
  </section>

  <section class='controls__btns'>
    <button id='rand'>random</button>
    <button id='apply'>apply</button>
    <button id='cancel'>cancel</button>
  </section>

  <button id='toggle'>toggle controls</button>
</section>

CSS

@charset "UTF-8";
html, body, .c {
  width: 100%;
  height: 100%;
}

body {
  overflow: hidden;
  margin: 0;
  background: radial-gradient(rgba(11, 35, 57, 0.001), rgba(0, 0, 0, 0.99)), linear-gradient(90deg, rgba(255, 255, 255, 0.4) 0.3125em, rgba(0, 0, 0, 0) 0.3125em) calc(50vw - 0.15625em) 0, linear-gradient(rgba(255, 255, 255, 0.4) 0.3125em, rgba(0, 0, 0, 0) 0.3125em) 0 calc(50vh - 0.15625em), linear-gradient(90deg, rgba(220, 220, 220, 0.15) 0.25em, rgba(0, 0, 0, 0) 0.25em) calc(50vw - 0.125em) 0, linear-gradient(rgba(220, 220, 220, 0.15) 0.25em, rgba(0, 0, 0, 0) 0.25em) 0 calc(50vh - 0.125em), linear-gradient(90deg, rgba(192, 192, 192, 0.1) 0.125em, rgba(0, 0, 0, 0) 0.125em) calc(50vw - 0.0625em) 0, linear-gradient(rgba(192, 192, 192, 0.1) 0.125em, rgba(0, 0, 0, 0) 0.125em) 0 calc(50vh - 0.0625em) #0b2339;
  background-size: 100% 100%, 100% 100%, 100% 100%, 10em 10em, 10em 10em, 2em 2em, 2em 2em;
  font: 1em verdana, sans-serif;
}

.c {
  position: absolute;
  z-index: -1;
}

.controls {
  position: absolute;
  bottom: 100%;
  padding: 0 .5em;
  background: #111;
  color: #eee;
  transition: .35s ease-out;
}
.controls--open {
  transform: translateY(100%);
}
.controls section {
  margin: .75em 0;
  padding: .5em;
  border-radius: .25em;
  box-shadow: 0 0 2px rgba(255, 255, 255, 0.25);
}
.controls button, .controls input, .controls [type='radio'] + label {
  cursor: pointer;
}
.controls button {
  border: none;
  font: 1em/2 verdana, sans-serif;
  transition: .3s;
}
.controls button:hover {
  color: greenyellow;
  background: #333;
}
.controls input[type='range'] {
  -webkit-appearance: none;
  display: block;
  margin: .5em 0 1em;
  padding: 0;
  width: 100%;
  height: 1.5em;
  background: grey;
}
.controls input[type='range'][id='hue'] {
  background: linear-gradient(90deg, #ff0000, #ff2b00, #ff5500, #ff8000, #ffaa00, #ffd500, #ffff00, #d4ff00, #aaff00, #80ff00, #55ff00, #2bff00, #00ff00, #00ff2b, #00ff55, #00ff80, #00ffaa, #00ffd5, #00ffff, #00d4ff,...

JavaScript

Object.getOwnPropertyNames(Math).map(function(p) {
  window[p] = Math[p];
});

var rand = function(min, max, isInt) {
  var max = ((max - 1) || 0) + 1, 
      min = min || 0, 
      gen = min + (max - min)*random();
    
  return (isInt)?(~~gen):gen;
};

var randsign = function() {
  return (random() < .5)?-1:1;
};

var c = document.querySelectorAll('.c'), 
    w, h, min_dim, ctx =[], 
    ctrls = document.querySelector('.controls'), 
    ctrl_c = 'hsl(84, 99%, 69%)', 
    r1_ctrl = document.getElementById('r1'), 
    r1, r1_f, r1_c = 'hsl(328, 100%, 75%)', 
    r2_ctrl = document.getElementById('r2'), 
    r2, r2_f, r2_c = 'hsl(60, 100%, 75%)', 
    sign, r2_rot, r2_r, 
    trace_ctrl = document.getElementById('d'), 
    d, d_f, 
    hue_ctrl = document.getElementById('hue'), 
    hue, 
    trace_c, 
    hypo_ctrl = document.getElementById('hypo'), 
    epi_ctrl = document.getElementById('epi'), 
    v_ctrl = document.getElementById('v'), 
    v_f, 
    rand_ctrl = document.getElementById('rand'), 
    ok_ctrl = document.getElementById('apply'), 
    no_ctrl = document.getElementById('cancel'), 
    toggle = document.getElementById('toggle'),
    prev_pos = null, 
    theta = 0, u = PI/180;
    t = 0, rID = null, running = false;

var setUpCanvas = function() {
  var s = getComputedStyle(c[0]);
  
  w = ~~s.width.split('px')[0];
  h = ~~s.height.split('px')[0];
  min_dim = min(w, h);
  
  for(var i = 0; i < 3; i++) {
    c[i].width = w;
    c[i].height = h;
    ctx[i] = c[i].getContext('2d');
    ctx[i].lineWidth = 3;
    ctx[i].translate(w/2, h/2);
  }
  
  initValues();
};

var initValues = function() {
  r1_f = 1*r1_ctrl.value;
  r2_f = 1*r2_ctrl.value;
  d_f = 1*trace_ctrl.value;
  v_f = 1*v_ctrl.value;
  
  sign = (hypo_ctrl.checked)?-1:1;
  hue = ~~hue_ctrl.value;
  trace_c = 'hsl(' + hue + ', 100%, 56%)'
  
  r1 = r1_f*min_dim/2;
  r2 = r2_f*r1;
  d = d_f*r2;
  
  r2_rot = r1 + sign*r2;
  r2_r = r2_rot/r2;
  
  if(rID) {
    cancelAnimationFrame(rID);
   ...