leumas-private-shared
Version:
Private React JSX Package For Leumas Shared Components, Headers, Footers, Asides, Login Pages, API Key Manager and much more. Styles and everything reusable to avoid DRY code across all of our subdomains
192 lines (160 loc) • 4.72 kB
JSX
import React, { useEffect, useRef } from 'react';
import { TweenLite, TweenMax, Power0 } from 'gsap/all';
import { styled } from '@mui/system';
import './Dots2.scss'; // Import the SCSS file here
const DotsWrapper = styled('div')`
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
`;
const Credits = styled('div')`
position: fixed;
bottom: 1rem;
right: 1rem;
font-size: 0.75rem;
display: flex;
align-items: center;
justify-content: flex-end;
color: var(--color);
`;
const Dots2Background = ({ children }) => {
const canvasRef = useRef(null);
useEffect(() => {
const { log } = console;
log('🎨');
const internals = {
config: {
totalGroups: 50,
},
colors: [
['#00ffff', '#ff0000'],
['#00ff00', '#ff00ff'],
['#0000ff', '#ffff00'],
],
random: (min, max) => min + Math.random() * (max - min),
};
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
const w = window.innerWidth;
const h = window.innerHeight;
canvas.width = w;
canvas.height = h;
class Shapes {
constructor(index) {
this.index = index;
this.offset = 50;
this.colorsIndex = 0;
this.draw(0);
this.reset().animate();
}
draw(colorsIndex) {
if (colorsIndex === undefined) {
this.colorsIndex = (this.colorsIndex + 1) % internals.colors.length;
}
const colors = internals.colors[this.colorsIndex];
ctx.clearRect(0, 0, w, h);
if (this.index % 2) {
ctx.fillStyle = colors[0];
ctx.fillRect(
internals.random(0, this.offset),
internals.random(0, this.offset),
60,
60
);
ctx.fillStyle = colors[1];
ctx.fillRect(
internals.random(0, this.offset),
internals.random(0, this.offset),
60,
60
);
} else {
ctx.fillStyle = colors[0];
ctx.beginPath();
ctx.arc(
internals.random(0, this.offset),
internals.random(0, this.offset),
30,
0,
Math.PI * 2
);
ctx.fill();
ctx.fillStyle = colors[1];
ctx.beginPath();
ctx.arc(
internals.random(0, this.offset),
internals.random(0, this.offset),
30,
0,
Math.PI * 2
);
ctx.fill();
}
return this;
}
animate() {
let positionX, positionY;
const rotation = internals.random(-360, 360);
const scale = internals.random(0.5, 1.25);
const delay = this.index * 0.1;
if (Math.random() > 0.5) {
positionX = internals.random(0 - w, w * 2);
positionY = Math.random() > 0.5 ? h * 2 : -h;
} else {
positionX = Math.random() > 0.5 ? w * 2 : -w;
positionY = internals.random(0 - h, h * 2);
}
TweenMax.to(this, internals.random(2, 6), {
x: positionX,
y: positionY,
rotation,
scale,
delay,
onComplete: () => {
this.reset().animate();
},
});
return this;
}
reset() {
this.x = w / 2;
this.y = h / 2;
this.rotation = 0;
this.scale = 0;
return this;
}
}
TweenLite.defaultEase = Power0.easeNone;
const shapes = [];
for (let i = 0; i < internals.config.totalGroups; i++) {
shapes.push(new Shapes(i));
}
function changeColors() {
shapes.forEach((shape) => shape.draw());
}
function resize() {
setTimeout(() => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}, 200);
}
window.addEventListener('click', changeColors);
window.addEventListener('touchstart', changeColors);
window.addEventListener('resize', resize);
window.addEventListener('orientationchange', resize);
return () => {
window.removeEventListener('click', changeColors);
window.removeEventListener('touchstart', changeColors);
window.removeEventListener('resize', resize);
window.removeEventListener('orientationchange', resize);
};
}, []);
return (
<DotsWrapper>
<canvas ref={canvasRef}></canvas>
{children}
</DotsWrapper>
);
};
export default Dots2Background;