react-snow-overlay
Version:
A performant snowfall effect for your website using canvas and web workers
3 lines (2 loc) • 5.74 kB
JavaScript
(function(n,i){typeof exports=="object"&&typeof module<"u"?i(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],i):(n=typeof globalThis<"u"?globalThis:n||self,i(n["react-snow-overlay"]={},n.jsxRuntime,n.React))})(this,function(n,i,r){"use strict";"use client";var I=n=>{throw TypeError(n)};var P=(n,i,r)=>i.has(n)||I("Cannot "+r);var A=(n,i,r)=>(P(n,i,"read from private field"),r?r.call(n):i.get(n)),S=(n,i,r)=>i.has(n)?I("Cannot add the same private member more than once"):i instanceof WeakSet?i.add(n):i.set(n,r),b=(n,i,r,D)=>(P(n,i,"write to private field"),D?D.call(n,r):i.set(n,r),r),h=(n,i,r)=>(P(n,i,"access private method"),r);var d,a,m;const D=Object.freeze({color:"rgba(255, 255, 255, 0.8)",maxParticles:50,speed:"DEFAULT"}),L={DEFAULT:33,FAST:20,FASTER:10},_=2**31-1,g=50,U=`(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)}}})();
`,R=typeof self<"u"&&self.Blob&&new Blob([U],{type:"text/javascript;charset=utf-8"});function F(e){let t;try{if(t=R&&(self.URL||self.webkitURL).createObjectURL(R),!t)throw"";const s=new Worker(t,{name:e==null?void 0:e.name});return s.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),s}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(U),{name:e==null?void 0:e.name})}finally{t&&(self.URL||self.webkitURL).revokeObjectURL(t)}}var f=(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))(f||{});class M{constructor(t){S(this,a);S(this,d);b(this,d,t)}init(t){h(this,a,m).call(this,{...t,type:f.INIT},[t.canvas])}updateSize(t){h(this,a,m).call(this,{...t,type:f.UPDATE_SIZE})}stop(){h(this,a,m).call(this,{type:f.STOP})}resume(){h(this,a,m).call(this,{type:f.RESUME})}updateOptions(t){h(this,a,m).call(this,{...t,type:f.UPDATE_OPTIONS})}terminate(){A(this,d).terminate()}}d=new WeakMap,a=new WeakSet,m=function(t,s){A(this,d).postMessage(t,{transfer:s})};const N=(e,t)=>{const s=r.useRef(null),l=r.useCallback((...u)=>{s.current!==null&&clearTimeout(s.current),s.current=window.setTimeout(()=>{e(...u)},t)},[e,t]);return r.useEffect(()=>()=>void(s.current!==null&&clearTimeout(s.current))),l},j=(e,t)=>{const s=r.useRef(null);return(!s.current||!v(t,s.current.key))&&(s.current={key:t,value:e()}),s.current.value},v=(e,t)=>{if(e===t)return!0;if(e===null||t===null||typeof e!="object"||typeof t!="object")return!1;const s=Object.keys(e),l=Object.keys(t);return!(s.length!==l.length||s.some(u=>!l.includes(u)||!v(e[u],t[u])))},C=r.memo(function({zIndex:t=_,disabled:s,disabledOnSingleCpuDevices:l,...u}){const O=r.useRef(null),p=r.useRef(null),c=r.useRef(null),[x,k]=r.useReducer(()=>!0,!1),y=j(()=>u,[u]),w=N(()=>{var o;if(!(typeof window>"u"||!((o=O.current)!=null&&o.transferControlToOffscreen))){if(p.current??(p.current=O.current.transferControlToOffscreen()),!c.current){c.current=new M(new F),k();const T=p.current;return c.current.init({canvas:T,width:window.innerWidth,height:window.innerHeight,options:y})}c.current.updateSize({width:window.innerWidth,height:window.innerHeight})}},g);r.useEffect(()=>(w(),window.addEventListener("resize",w),()=>window.removeEventListener("resize",w)),[w]);const E=r.useMemo(()=>{const o=!!s,T=l&&typeof navigator<"u"&&navigator.hardwareConcurrency===1;return o||T},[l,s]);return r.useEffect(()=>{if(!(!x||!p.current||!c.current)){if(E)return c.current.stop();c.current.updateOptions({options:y})}},[E,y,x]),r.useEffect(()=>{var o;(o=c.current)==null||o[E?"stop":"resume"]()},[E]),r.useEffect(()=>{var o;return(o=c.current)==null?void 0:o.terminate},[]),i.jsx("canvas",{"aria-hidden":"true",ref:O,style:{zIndex:t,pointerEvents:"none",userSelect:"none",position:"fixed",top:0,right:0,bottom:0,left:0,...E&&{display:"none"}}})});n.DEFAULT_SNOW_OPTIONS=D,n.SNOW_OPTIONS_SPEED_MAP=L,n.SnowOverlay=C,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})});