UNPKG

react-snow-overlay

Version:

A performant snowfall effect for your website using canvas and web workers

176 lines (175 loc) 6.79 kB
"use client"; var T = (e) => { throw TypeError(e); }; var O = (e, t, n) => t.has(e) || T("Cannot " + n); var U = (e, t, n) => (O(e, t, "read from private field"), n ? n.call(e) : t.get(e)), A = (e, t, n) => t.has(e) ? T("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(e) : t.set(e, n), x = (e, t, n, r) => (O(e, t, "write to private field"), r ? r.call(e, n) : t.set(e, n), n), a = (e, t, n) => (O(e, t, "access private method"), n); import { jsx as g } from "react/jsx-runtime"; import { useRef as p, useCallback as I, useEffect as m, memo as L, useReducer as F, useMemo as M } from "react"; const q = Object.freeze({ color: "rgba(255, 255, 255, 0.8)", maxParticles: 50, speed: "DEFAULT" }), H = { DEFAULT: 33, FAST: 20, FASTER: 10 }, _ = 2 ** 31 - 1, N = 50, R = `(function(){"use strict";const D=Object.freeze({color:"rgba(255, 255, 255, 0.8)",maxParticles:50,speed:"DEFAULT"}),S={DEFAULT:33,FAST:20,FASTER:10},x=e=>e.type===0,A=e=>e.type===1,w=e=>e.type===2,P=e=>e.type===3,F=e=>e.type===4,O=e=>typeof e=="object"?e.msBetweenUpdates:S[e];let o={...D},a,h=0,y=-1/0,l=null,c,i,d=!1;self.onmessage=e=>{const{data:s}=e;if(x(s))c=s.canvas,i=c.getContext("2d"),c.width=s.width,c.height=s.height,o={...D,...s.options},a=Array.from({length:o.maxParticles},M);else if(A(s))c.width=s.width,c.height=s.height;else if(P(s)){const{type:m,...r}=s;o={...o,...r.options},T(o.maxParticles)}else if(w(s)){d=!0;const{width:m,height:r}=i.canvas;i.clearRect(0,0,m,r),l&&cancelAnimationFrame(l);return}else F(s)&&(d=!1);const p=()=>{const m=O(o.speed);if(performance.now()-y<m){l=requestAnimationFrame(p);return}const{width:r,height:f}=i.canvas;i.clearRect(0,0,r,f),i.fillStyle=o.color,i.beginPath();for(let n=0;n<o.maxParticles;n++){const t=a[n];i.moveTo(t.x,t.y),i.arc(t.x,t.y,t.r,0,Math.PI*2,!0)}i.fill(),h=(h+.01)%360;const g=Math.sin(h),U=Math.cos(h);for(let n=0;n<o.maxParticles;n++){const t=a[n],W=U*t.cosD-g*t.sinD;if(t.y+=W+1+t.r/2,t.x+=g*2,t.x>r+5||t.x<-5||t.y>f)if(n%3>0)a[n]={x:Math.random()*r,y:-10,r:t.r,d:t.d,sinD:t.sinD,cosD:t.cosD};else{const u=Math.random()*r;g>0?a[n]={x:-5-u,y:Math.random()*f,r:t.r,d:t.d,sinD:t.sinD,cosD:t.cosD}:a[n]={x:r+5+u,y:Math.random()*f,r:t.r,d:t.d,sinD:t.sinD,cosD:t.cosD}}}y=performance.now(),d||(l=requestAnimationFrame(p))};l&&cancelAnimationFrame(l),d||requestAnimationFrame(p)};const T=e=>{const s=a.length;if(e!==s){if(e<s)return a.splice(e,s-e);a.push(...Array.from({length:e-s},M))}},M=()=>{const e=Math.random()*o.maxParticles;return{x:Math.random()*c.width,y:Math.random()*-c.height,r:Math.random()*4+1,d:e,sinD:Math.sin(e),cosD:Math.cos(e)}}})(); `, v = typeof self < "u" && self.Blob && new Blob([R], { type: "text/javascript;charset=utf-8" }); function C(e) { let t; try { if (t = v && (self.URL || self.webkitURL).createObjectURL(v), !t) throw ""; const n = new Worker(t, { name: e == null ? void 0 : e.name }); return n.addEventListener("error", () => { (self.URL || self.webkitURL).revokeObjectURL(t); }), n; } catch { return new Worker( "data:text/javascript;charset=utf-8," + encodeURIComponent(R), { name: e == null ? void 0 : e.name } ); } finally { t && (self.URL || self.webkitURL).revokeObjectURL(t); } } var u = /* @__PURE__ */ ((e) => (e[e.INIT = 0] = "INIT", e[e.UPDATE_SIZE = 1] = "UPDATE_SIZE", e[e.STOP = 2] = "STOP", e[e.UPDATE_OPTIONS = 3] = "UPDATE_OPTIONS", e[e.RESUME = 4] = "RESUME", e))(u || {}), d, c, l; class k { constructor(t) { A(this, c); A(this, d); x(this, d, t); } init(t) { a(this, c, l).call(this, { ...t, type: u.INIT }, [t.canvas]); } updateSize(t) { a(this, c, l).call(this, { ...t, type: u.UPDATE_SIZE }); } stop() { a(this, c, l).call(this, { type: u.STOP }); } resume() { a(this, c, l).call(this, { type: u.RESUME }); } updateOptions(t) { a(this, c, l).call(this, { ...t, type: u.UPDATE_OPTIONS }); } terminate() { U(this, d).terminate(); } } d = new WeakMap(), c = new WeakSet(), l = function(t, n) { U(this, d).postMessage(t, { transfer: n }); }; const z = (e, t) => { const n = p(null), r = I( (...o) => { n.current !== null && clearTimeout(n.current), n.current = window.setTimeout(() => { e(...o); }, t); }, [e, t] ); return m( () => () => void (n.current !== null && clearTimeout(n.current)) ), r; }, j = (e, t) => { const n = p(null); return (!n.current || !S(t, n.current.key)) && (n.current = { key: t, value: e() }), n.current.value; }, S = (e, t) => { if (e === t) return !0; if (e === null || t === null || typeof e != "object" || typeof t != "object") return !1; const n = Object.keys(e), r = Object.keys(t); return !(n.length !== r.length || n.some( (o) => !r.includes(o) || !S(e[o], t[o]) )); }, V = L(function({ zIndex: t = _, disabled: n, disabledOnSingleCpuDevices: r, ...o }) { const w = p(null), f = p(null), i = p(null), [P, b] = F( () => !0, !1 ), E = j(() => o, [o]), D = z(() => { var s; if (!(typeof window > "u" || // If browser doesn't support OffscreenCanvas, don't bother !((s = w.current) != null && s.transferControlToOffscreen))) { if (f.current ?? (f.current = w.current.transferControlToOffscreen()), !i.current) { i.current = new k(new C()), b(); const y = f.current; return i.current.init({ canvas: y, width: window.innerWidth, height: window.innerHeight, options: E }); } i.current.updateSize({ width: window.innerWidth, height: window.innerHeight }); } }, N); m(() => (D(), window.addEventListener("resize", D), () => window.removeEventListener("resize", D)), [D]); const h = M(() => { const s = !!n, y = r && typeof navigator < "u" && navigator.hardwareConcurrency === 1; return s || y; }, [r, n]); return m(() => { if (!(!P || !f.current || !i.current)) { if (h) return i.current.stop(); i.current.updateOptions({ options: E }); } }, [h, E, P]), m(() => { var s; (s = i.current) == null || s[h ? "stop" : "resume"](); }, [h]), m(() => { var s; return (s = i.current) == null ? void 0 : s.terminate; }, []), /* @__PURE__ */ g( "canvas", { "aria-hidden": "true", ref: w, style: { zIndex: t, pointerEvents: "none", userSelect: "none", position: "fixed", top: 0, right: 0, bottom: 0, left: 0, ...h && { display: "none" } } } ); }); export { q as DEFAULT_SNOW_OPTIONS, H as SNOW_OPTIONS_SPEED_MAP, V as SnowOverlay };