mirror of
https://github.com/elyby/accounts-frontend.git
synced 2024-12-27 07:20:23 +05:30
159 lines
3.7 KiB
JavaScript
159 lines
3.7 KiB
JavaScript
import Box from './Box';
|
||
|
||
/**
|
||
* Основано на http://codepen.io/mladen___/pen/gbvqBo
|
||
*/
|
||
export default class BoxesField {
|
||
/**
|
||
* @param {HTMLCanvasElement} elem - canvas DOM node
|
||
* @param {object} params
|
||
*/
|
||
constructor(
|
||
elem,
|
||
params = {
|
||
countBoxes: 14,
|
||
boxMinSize: 20,
|
||
boxMaxSize: 75,
|
||
backgroundColor: '#233d49',
|
||
lightColor: '#28555b',
|
||
shadowColor: '#274451',
|
||
boxColors: [
|
||
'#207e5c',
|
||
'#5b9aa9',
|
||
'#e66c69',
|
||
'#6b5b8c',
|
||
'#8b5d79',
|
||
'#dd8650',
|
||
],
|
||
},
|
||
) {
|
||
this.elem = elem;
|
||
const ctx = elem.getContext('2d');
|
||
|
||
if (!ctx) {
|
||
throw new Error('Can not get canvas 2d context');
|
||
}
|
||
|
||
this.ctx = ctx;
|
||
this.params = params;
|
||
|
||
this.light = {
|
||
x: 160,
|
||
y: 200,
|
||
};
|
||
|
||
this.resize();
|
||
this.drawLoop();
|
||
this.bindWindowListeners();
|
||
|
||
/**
|
||
* @type {Box[]}
|
||
*/
|
||
this.boxes = [];
|
||
|
||
while (this.boxes.length < this.params.countBoxes) {
|
||
this.boxes.push(
|
||
new Box({
|
||
size: Math.floor(
|
||
Math.random() * (this.params.boxMaxSize - this.params.boxMinSize) +
|
||
this.params.boxMinSize,
|
||
),
|
||
startX: Math.floor(Math.random() * elem.width + 1),
|
||
startY: Math.floor(Math.random() * elem.height + 1),
|
||
startRotate: Math.random() * Math.PI,
|
||
color: this.getRandomColor(),
|
||
shadowColor: this.params.shadowColor,
|
||
}),
|
||
);
|
||
}
|
||
}
|
||
|
||
resize() {
|
||
const { width, height } = this.elem.getBoundingClientRect();
|
||
this.elem.width = width;
|
||
this.elem.height = height;
|
||
}
|
||
|
||
drawLight(light) {
|
||
const greaterSize =
|
||
window.screen.width > window.screen.height
|
||
? window.screen.width
|
||
: window.screen.height;
|
||
// еее, теорема пифагора и описывание окружности вокруг квадрата, не зря в универ ходил!!!
|
||
const lightRadius = greaterSize * Math.sqrt(2);
|
||
|
||
this.ctx.beginPath();
|
||
this.ctx.arc(light.x, light.y, lightRadius, 0, 2 * Math.PI);
|
||
const gradient = this.ctx.createRadialGradient(
|
||
light.x,
|
||
light.y,
|
||
0,
|
||
light.x,
|
||
light.y,
|
||
lightRadius,
|
||
);
|
||
gradient.addColorStop(0, this.params.lightColor);
|
||
gradient.addColorStop(1, this.params.backgroundColor);
|
||
this.ctx.fillStyle = gradient;
|
||
this.ctx.fill();
|
||
}
|
||
|
||
drawLoop() {
|
||
this.ctx.clearRect(0, 0, this.elem.width, this.elem.height);
|
||
this.drawLight(this.light);
|
||
|
||
for (const i in this.boxes) {
|
||
if (!this.boxes.hasOwnProperty(i)) {
|
||
continue;
|
||
}
|
||
|
||
const box = this.boxes[i];
|
||
box.rotate();
|
||
box.drawShadow(this.ctx, this.light);
|
||
}
|
||
|
||
for (const i in this.boxes) {
|
||
if (!this.boxes.hasOwnProperty(i)) {
|
||
continue;
|
||
}
|
||
|
||
const box = this.boxes[i];
|
||
box.draw(this.ctx);
|
||
|
||
// Если квадратик вылетел за пределы экрана
|
||
if (box.y - box.halfSize > this.elem.height) {
|
||
box.y -= this.elem.height + 100;
|
||
this.updateBox(box);
|
||
}
|
||
|
||
if (box.x - box.halfSize > this.elem.width) {
|
||
box.x -= this.elem.width + 100;
|
||
this.updateBox(box);
|
||
}
|
||
}
|
||
|
||
requestAnimationFrame(this.drawLoop.bind(this));
|
||
}
|
||
|
||
bindWindowListeners() {
|
||
window.addEventListener('resize', this.resize.bind(this));
|
||
window.addEventListener('mousemove', event => {
|
||
this.light.x = event.clientX;
|
||
this.light.y = event.clientY;
|
||
});
|
||
}
|
||
|
||
/**
|
||
* @param {Box} box
|
||
*/
|
||
updateBox(box) {
|
||
box.color = this.getRandomColor();
|
||
}
|
||
|
||
getRandomColor() {
|
||
return this.params.boxColors[
|
||
Math.floor(Math.random() * this.params.boxColors.length)
|
||
];
|
||
}
|
||
}
|