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
152 lines (128 loc) • 4.33 kB
JSX
import React, { useEffect, useRef } from 'react';
import { styled } from '@mui/system';
import './NoiseBackground.scss'; // Import the SCSS file here
const NoiseWrapper = styled('div')`
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
z-index: -1;
pointer-events: none;
`;
const loadScript = (src) => {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = src;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
};
const NoiseBackground = ({ children }) => {
const canvasRef = useRef(null);
useEffect(() => {
const initialize = async () => {
await loadScript('https://rawgithub.com/jwagner/simplex-noise.js/master/simplex-noise.js');
const noise = new window.SimplexNoise();
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
const resizeCanvas = () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
};
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
const TAU = Math.PI * 2;
const THIRD = 1 / 3;
const TWO_THIRDS = 2 / 3;
const ZERO = 0;
const ONE = 1;
const map = (value, start1, stop1, start2, stop2) => {
return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
};
const background = (fillStyle) => {
ctx.fillStyle = fillStyle;
ctx.fillRect(0, 0, canvas.width, canvas.height);
};
const beginPath = () => {
ctx.beginPath();
};
const moveTo = (x, y) => {
ctx.moveTo(x, y);
};
const lineTo = (x, y) => {
ctx.lineTo(x, y);
};
const compositeOperation = (operation) => {
ctx.globalCompositeOperation = operation;
};
const stroke = (strokeStyle, lineWidth) => {
ctx.strokeStyle = strokeStyle;
ctx.lineWidth = lineWidth;
ctx.stroke();
};
const hsl = (h, s, l, a = 1) => `hsla(${h},${s}%,${l}%,${a})`;
const draw = (e) => {
const width = canvas.width;
const height = canvas.height;
const width_half = width / 2;
const height_half = height / 2;
let xCount = 35;
let yCount = 80;
let iXCount = 1 / (xCount - 1);
let iYCount = 1 / (yCount - 1);
let time = e * 0.001;
let timeStep = 0.01;
let grad = ctx.createLinearGradient(-width, 0, width, height);
let t = time % 1;
let tSide = Math.floor(time % 2) === 0;
let hueA = tSide ? 340 : 210;
let hueB = !tSide ? 340 : 210;
let colorA = hsl(hueA, 100, 50);
let colorB = hsl(hueB, 100, 50);
grad.addColorStop(map(t, 0, 1, ZERO, THIRD), colorA);
grad.addColorStop(map(t, 0, 1, THIRD, TWO_THIRDS), colorB);
grad.addColorStop(map(t, 0, 1, TWO_THIRDS, ONE), colorA);
ctx.globalAlpha = map(Math.cos(time), -1, 1, 0.15, 0.3);
background(grad);
ctx.globalAlpha = 1;
beginPath();
for (let j = 0; j < yCount; j++) {
let tj = j * iYCount;
let c = Math.cos(tj * TAU + time) * 0.1;
for (let i = 0; i < xCount; i++) {
let t = i * iXCount;
let n = noise.noise3D(t, time, c);
let y = n * height_half;
let x = t * (width + 20) - width_half - 10;
(i ? lineTo : moveTo)(x, y);
}
time += timeStep;
}
compositeOperation('lighter');
ctx.filter = 'blur(10px)';
stroke(grad, 5);
ctx.filter = 'blur(5px)';
stroke(hsl(0, 0, 100, 0.8), 2);
};
const animate = (time) => {
draw(time);
requestAnimationFrame(animate);
};
requestAnimationFrame(animate);
return () => {
window.removeEventListener('resize', resizeCanvas);
};
};
initialize();
}, []);
return (
<NoiseWrapper>
<canvas ref={canvasRef}></canvas>
{children}
</NoiseWrapper>
);
};
export default NoiseBackground;