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);
...