Inspired from the Spirograph, this experiment allows you to create beautiful flowers and more ! Have fun with the controls by pressing space.
A Pen by Louis Hoebregts on CodePen.
Inspired from the Spirograph, this experiment allows you to create beautiful flowers and more ! Have fun with the controls by pressing space.
A Pen by Louis Hoebregts on CodePen.
<canvas id="canvas"></canvas> | |
<div class="form" id="form"> | |
<p><label>Circles</label><input type="range" min="1" max="25" value="5" id="circles" /></p> | |
<p><label>Size</label><input type="range" min="1" max="50" value="10" id="size" /></p> | |
<p><label>Number</label><input type="range" min="1" max="12" value="6" id="number" /></p> | |
<p><label>Speed</label><input type="range" min="0" max="199" value="50" id="speed" /></p> | |
<p><label>Color</label><input type="color" value="#ffffff" id="color" /></p> | |
<button id="close">Close</button> | |
</div> | |
<p id="tip">Press space for controls</p> |
window.requestAnimFrame = (function(){ | |
return window.requestAnimationFrame || | |
window.webkitRequestAnimationFrame || | |
window.mozRequestAnimationFrame || | |
function( callback ){ | |
window.setTimeout(callback, 1000 / 60); | |
}; | |
})(); | |
var canvas = document.getElementById('canvas'), | |
ctx = canvas.getContext('2d'), | |
ww = window.innerWidth, | |
wh = window.innerHeight, | |
g = [ww/15, wh/15], | |
fps = 25, | |
j = 0, | |
c = 5, | |
size = 10, | |
n = 8 | |
speed = 50; | |
canvas.width = ww; | |
canvas.height = wh; | |
ctx.fillStyle="rgba(255,255,255,.5)"; | |
ctx.strokeStyle="rgba(255,255,255,.6)"; | |
function draw() { | |
setTimeout(function() { | |
requestAnimationFrame(draw); | |
ctx.clearRect(0,0,ww, wh); | |
ctx.save(); | |
ctx.translate( ww/2,wh/2 ); | |
ctx.rotate(j/(speed*2)); | |
ctx.translate( -ww/2,-wh/2 ); | |
for(var i=0;i<n;i++){ | |
ctx.translate( ww/2,wh/2 ); | |
ctx.rotate(Math.PI/(n/2)); | |
ctx.translate( -ww/2,-wh/2 ); | |
for(var k=1;k<c;k++){ | |
ctx.beginPath(); | |
ctx.arc(ww/2+g[0]*2, wh/2+g[1]*2, k*size, 0, Math.PI*2, false); | |
ctx.stroke(); | |
ctx.closePath(); | |
} | |
} | |
ctx.restore(); | |
j++; | |
}, 1000 / fps); | |
}; | |
draw(); | |
//CONTROLS | |
document.body.addEventListener("mousemove", function(e){ | |
g = [ww/2-e.x, wh/2-e.y]; | |
}); | |
var controls = true; | |
document.body.addEventListener("keypress", function(e){ | |
if(e.keyCode==32 && controls){ | |
document.getElementById("form").classList.add("visible"); | |
document.getElementById("form").style.left = (ww/2-g[0])+"px"; | |
document.getElementById("form").style.top = (wh/2-g[1])+"px"; | |
document.getElementById("tip").innerHTML = "Press space to hide controls."; | |
} | |
else{ | |
document.getElementById("form").classList.remove("visible"); | |
document.getElementById("tip").innerHTML = "Press space for controls"; | |
} | |
}); | |
document.body.addEventListener("keyup", function(e){ | |
if(e.keyCode==32){ | |
controls = !controls; | |
} | |
}); | |
document.getElementById("circles").addEventListener("input", function(){ | |
c = this.value; | |
}); | |
document.getElementById("size").addEventListener("input", function(){ | |
size = this.value; | |
}); | |
document.getElementById("number").addEventListener("input", function(){ | |
n = this.value; | |
}); | |
document.getElementById("color").addEventListener("input", function(){ | |
ctx.strokeStyle = this.value; | |
}); | |
document.getElementById("speed").addEventListener("input", function(){ | |
speed = 200-this.value; | |
if(this.value==0)speed=0; | |
}); | |
document.getElementById("close").addEventListener("click", function(){ | |
document.getElementById("form").classList.remove("visible"); | |
document.getElementById("tip").innerHTML = "Press space for controls"; | |
controls=true; | |
}); |
html,body{ | |
width: 100%; | |
height: 100%; | |
margin: 0; | |
padding: 0; | |
background: black; | |
overflow: hidden; | |
font-family: Helvetica, arial, sans-serif; | |
} | |
.form{ | |
position: fixed; | |
left: 10px; | |
top: 10px; | |
color: white; | |
border: 1px solid white; | |
padding: 10px; | |
display: none; | |
} | |
.form button{background: black;color: white;width:100%;} | |
.form.visible{display: block;} | |
.form p:first-child{margin-top: 0;} | |
button, input{width: 100px;float: right;} | |
p{margin: 15px 0;text-align: left;clear: both;} | |
label{margin-right: 15px;} | |
#tip{position: absolute;bottom:0px;left:10px;color: white;} |