UNPKG

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
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;