I've written a simple app that draws with a kaleidoscope effect in javascript, could someone please review the code? I'm especially interested in functional practices and design patterns.
const game = {
pi2: Math.PI*2,
sides: 12,
background: '125,125,125',
load: function () {
game.canvas = document.createElement('canvas');
game.ctx = game.canvas.getContext('2d');
document.body.appendChild(game.canvas);
document.body.style.overflow = 'hidden';
document.body.style.background = 'rgba('+game.background+',1)';
game.resize();
game.input = document.querySelector('input');
game.input.addEventListener('change', game.change);
game.change();
game.button = document.querySelector('button');
game.button.addEventListener('click', game.clear);
game.clear();
},
getPoint: function (event) {
return {
x: event.clientX - game.hw,
y: event.clientY - game.hh
};
},
mousedown: function (event) {
game.clicking = true;
},
mouseup: function (event) {
game.clicking = false;
},
draw: function (event) {
game.point = game.getPoint(event);
if (game.last) {
if (game.clicking) {
game.ctx.fillStyle = 'rgba('+game.background+',0.01)';
game.ctx.fillRect(0,0,innerWidth, innerHeight);
}
var angle1 = Math.atan2(game.last.y,game.last.x);
var angle2 = Math.atan2(game.point.y,game.point.x);
for (var i=0; i<game.sides; i++) {
angle1 += game.slice;
angle2 += game.slice;
var p1 = game.rotate(angle1, game.last);
var p2 = game.rotate(angle2, game.point);
var h = Math.round((angle1*360)/game.pi2);
var color = 'hsl('+h+',5%,50%)';
game.ctx.lineWidth = 1;
if (game.clicking || game.clicking !== game.release) {
color = 'hsl('+h+',100%,75%)';
game.ctx.lineWidth = 3;
}
if (game.clicking !== game.release) {
game.circle(p2,color);
}
game.line(p1,p2,color);
}
}
game.last = game.point;
game.release = game.clicking;
},
rotate: function (a,p) {
var d = Math.sqrt(Math.pow(p.x,2)+Math.pow(p.y,2));
return {
x: d * Math.cos(a),
y: d * Math.sin(a)
}
},
line: function (a,b,c) {
game.ctx.beginPath();
game.ctx.strokeStyle = c;
game.ctx.moveTo(a.x + game.hw, a.y + game.hh);
game.ctx.lineTo(b.x + game.hw, b.y + game.hh);
game.ctx.stroke();
},
circle: function (p,c) {
game.ctx.beginPath();
game.ctx.strokeStyle = c;
game.ctx.arc(p.x + game.hw, p.y + game.hh, 3, 0, game.pi2);
game.ctx.stroke();
},
resize: function () {
game.canvas.width = innerWidth;
game.canvas.height = innerHeight;
game.hw = innerWidth/2;
game.hh = innerHeight/2;
},
change: function () {
game.sides = game.input.value;
game.slice = game.pi2 / game.sides;
},
clear: function () {
game.ctx.fillStyle = 'rgba('+game.background+',1)';
game.ctx.fillRect(0,0,innerWidth, innerHeight);
}
};
addEventListener('load', game.load);
addEventListener('mousedown', game.mousedown);
addEventListener('mouseup', game.mouseup);
addEventListener('resize', game.resize);
addEventListener('mousemove', game.draw);
body {
overflow: hidden;
cursor: crosshair;
}
div {
position: absolute;
margin: 0.2em;
margin-left: calc(50% - 3em);
background: rgba(255,255,255,0.8);
padding: 0 0.3em;
border-radius: 0.3em;
}
input {
width: 3em;
padding: 0.2em;
margin: 0.3em;
}
button {
padding: 0.2em 0.5em;
}
<div>
<label>Sides:</label>
<input type="number" value="7" min="1">
<button>X</button>
</div>