starfield-react
Version:
A React component that draws an animated Starfield on a canvas dom element.
3 lines (2 loc) • 3.32 kB
JavaScript
var t=require("react");function e(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var n=e(t);function r(t){let e=t.width,n=t.height,r=Math.round(e/2),o=Math.round(n/2),s=(e+n)/2;return{stars:i(r,o,s,e,n,t.count),width:e,height:n,x:r,y:o,z:s}}function i(t,e,n,r,i,o){let s=[];for(let a=0;a<o;a++)s.push({x:Math.random()*r*2-2*t,y:Math.random()*i*2-2*e,z:Math.round(Math.random()*n),stepX:0,stepY:0});return s}function o(e,n,i){const o=(null==i?void 0:i.current)||r({count:n.count,height:n.height,width:n.width});if(n.count!==o.stars.length)if(o.stars.length<n.count){const{stars:t}=r({count:n.count-o.stars.length,height:n.height,width:n.width});o.stars=[...o.stars,...t]}else o.stars.splice(0,o.stars.length-n.count);if(n.width!==o.width||n.height!==o.height){const{stars:t}=r({count:n.count,height:n.height,width:n.width});o.stars=t,o.width=n.width,o.height=n.height,o.x=Math.round(n.width/2),o.y=Math.round(n.height/2),o.z=(n.width+n.height)/2}t.useEffect(()=>{if(!e.current)return;const t=e.current.getContext("2d");if(!t)return;const r=1/o.z,{speed:i,starRatio:s,starSize:a}=n;"string"==typeof n.starStyle&&(t.strokeStyle=n.starStyle),t.lineCap=n.starShape;const h=1e3/n.fps;let u,d,c,l=Date.now();return u=requestAnimationFrame(function e(){t&&(u=requestAnimationFrame(e),d=Date.now(),c=d-l,c<h||(l=d-c%h,function({context:t,stars:e,width:n,height:r,z:i,x:o,y:s,starLineWidthRatio:a,speed:h,starRatio:u,starSize:d,strokeStyle:c,bgStyle:l,clear:g,noBackground:f}){g&&(t.clearRect(0,0,n,r),f||(t.fillStyle=l,t.fillRect(0,0,n,r)));let w=!1;for(let l=0;l<e.length;l++){"function"==typeof c&&(t.strokeStyle=c());let g=e[l],f=g.stepX,p=g.stepY;w=!0,g.z-=h,g.z>i&&(g.z-=i,w=!1),g.z<0&&(g.z+=i,w=!1),g.stepX=o+g.x/g.z*u,g.stepY=s+g.y/g.z*u,w=w&&f>0&&f<n&&p>0&&p<r,w&&(t.beginPath(),t.lineWidth=(1-a*g.z)*d,t.moveTo(f,p),t.lineTo(g.stepX,g.stepY),t.stroke(),t.closePath())}}({context:t,speed:i,starRatio:s,starSize:a,starLineWidthRatio:r,strokeStyle:n.starStyle,bgStyle:n.bgStyle,noBackground:n.noBackground,clear:n.clear,...o})))}),()=>cancelAnimationFrame(u)},[n])}const s=({width:e=300,height:i=300,starStyle:s="#fff",bgStyle:a="#000",count:h=3e3,speed:u=3,starRatio:d=356,starSize:c=1.4,starShape:l="round",clear:g=!0,noBackground:f=!1,fps:w=10,...p})=>{const S=t.useRef(null);return o(S,{width:e,height:i,starStyle:s,bgStyle:a,count:h,fps:w,speed:u,starRatio:d,starShape:l,starSize:c,clear:g,noBackground:f},t.useRef(r({count:h,height:i,width:e}))),n.default.createElement("canvas",Object.assign({ref:S},{width:e,height:i},p))};function a(){let[e,n]=t.useState(h());function r(){n(h())}return t.useEffect(()=>(window.addEventListener("resize",r),()=>{window.removeEventListener("resize",r)}),[]),e}function h(){return{innerHeight:window.innerHeight,innerWidth:window.innerWidth,outerHeight:window.outerHeight,outerWidth:window.outerWidth}}const u={position:"fixed",zIndex:-1};exports.StarField=s,exports.WindowSizeStarField=({style:t,...e})=>{const{innerWidth:r,innerHeight:i}=a();return n.default.createElement(s,Object.assign({},e,{style:{...u,...t},width:r,height:i}))},exports.randomColor=function(){return`#${Array.apply(null,new Array(6)).map(()=>"0123456789ABCDEF"[Math.floor(16*Math.random())]).join("")}`},exports.useStarField=o,exports.useWindowSize=a;
//# sourceMappingURL=starfield-react.js.map