react-snow-overlay
Version:
A performant snowfall effect for your website using canvas and web workers
176 lines (175 loc) • 6.65 kB
JavaScript
"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
};