HTML
<div class="select-fields">
<select class="select modeSelect">
<option value="os">oscillator</option>
<option value="as">aster</option>
<option value="mt">metronome</option>
</select>
<select class="select colorSelect">
<option value="bw">black and white</option>
<option value="co">color</option>
</select>
</div>
<div class="canvas-wrapper">
<canvas id="canvas">Canvas most be where!</canvas>
</div>
SCSS
@import url('https://fonts.googleapis.com/css?family=Josefin+Sans');
$font: 'Josefin Sans', sans-serif;
*{
box-sizing: border-box;
}
html,body{
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
.canvas-wrapper{
position: absolute;
display: block;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 0;
width: 600px;
height: 600px;
box-shadow: 7px 7px 10px #444;
}
.select-fields{
display: flex;
flex-direction: row;
width: 350px;
padding: 1em;
z-index: 2;
position: relative;
.select{
margin-right: 1em;
font-size: 1.2em;
font-family: $font;
padding: .2em;
border-radius: 5px;
}
}
JAVASCRIPT
const canvas = document.getElementById('canvas');
const modeSelect = document.querySelector('.modeSelect');
const colorSelect = document.querySelector('.colorSelect');
const ctx = canvas.getContext('2d');
const w = canvas.width = 600;
const h = canvas.height = 600;
const {sin, cos, PI, random, tan, floor} = Math;
let objectsArray = [];
let oblen = objectsArray.length;
let objectsAmount = 100;
let maxSize = 25;
let minSize = 2;
let mode = 'os';
let color = 'bw';
let metronome = false;
function changeParameters(){
modeSelect.addEventListener('change', (e)=>{
mode = e.target.value;
});
colorSelect.addEventListener('change', (e)=>{
color = e.target.value;
});
}
class CircObject {
constructor(center, radius, ctx) {
this.center = center;
this.radius = radius;
this.ctx = ctx;
this.smX = random()*(0.2 - (-0.2)) + (-0.2);
this.smY = random()*(0.2 - (-0.2)) + (-0.2);
this.randomSpeed = random()*(1 - (-1)) + (-1);
this.color = `hsl(${floor(random()*356)}, 100%, 50%)`;
}
circInit(angleFactor, color, metronome){
// reflection logic
if(this.center.x + this.radius >= w){
this.smX = -this.smX;
}
if(this.center.x <= this.radius ){
this.smX = -this.smX;
}
if(this.center.y + this.radius >= h){
this.smY = -this.smY;
}
if(this.center.y <= this.radius ){
this.smY = -this.smY;
}
// move objects
this.cx = this.center.x += this.smX;
this.cy = this.center.y += this.smY;
this.speed = this.randomSpeed * (metronome ? cos(angleFactor * 1.2) : angleFactor);
// draw objects
this.ctx.beginPath();
this.ctx.moveTo(this.cx, this.cy);
this.ctx.lineTo(this.cx-sin(this.speed)*this.radius, this.cy-cos(this.speed)*this.radius);
this.ctx.strokeStyle = (color == 'co' ? this.color : '#fff');
this.ctx.stroke();
this.ctx.closePath();
}
}
for(let i = 0; i < objectsAmount; i++){
let xPos = floor(random()*((w - maxSize) - maxSize ) + maxSize);
let yPos = floor(random()*((h - maxSize) - maxSize ) + maxSize);
let radius = floor(random()*(maxSize - minSize )+ minSize);
objectsArray.push(new CircObject({x: xPos, y: yPos }, radius, ctx));
}
function paintObjects(tick){
let a, c, m;
switch(mode){
case 'os' : a = tick; break;
case 'as' : a = random() * tick; break;
case 'mt' : a = tick , m = true; break;
}
switch(color){
case 'co' : c = 'co'; break;
case 'bw' : c = 'bw'; break;
}
for(let i = 0, len = objectsArray.length; i < len; i++){
objectsArray[i].circInit(a, c, m);
}
}
let ti = 0;
function animateBox(){
changeParameters();
ctx.fillStyle='rgba(0,0,0, .01)';
ctx.fillRect(0,0,w,h);
paintObjects(ti);
ti += 0.1;
window.requestAnimationFrame(animateBox);
}
animateBox();