UNPKG

react-snow-overlay

Version:

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

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