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;} |