UNPKG

react-framage

Version:

Display portions of an image, flipbook animate between them and apply nineslice scaling!

3 lines (2 loc) 5.69 kB
import{jsx as e}from"react/jsx-runtime";import{useState as t,useRef as i,useCallback as n,useEffect as r,createContext as a,useContext as l}from"react";if(!document.querySelector("style[data-react-framage-style]")){const e=document.createElement("style");e.setAttribute("data-react-framage-style",""),e.innerHTML="react-framage,\nreact-framage-slice {\n position: relative;\n overflow: hidden;\n}\n\nreact-framage {\n display: inline-block;\n width: var(--fallback-width);\n height: var(--fallback-height);\n}\n\nreact-framage:where([ninesliced]) {\n display: inline-grid;\n grid-template-rows: var(--nineslice-top, var(--nineslice, var(--fallback-nineslice-top))) 1fr var(--nineslice-bottom, var(--nineslice, var(--fallback-nineslice-bottom)));\n grid-template-columns: var(--nineslice-left, var(--nineslice, var(--fallback-nineslice-left))) 1fr var(--nineslice-right, var(--nineslice, var(--fallback-nineslice-right)));\n}\n\nreact-framage-slice {\n width: 100%;\n height: 100%;\n}\n\nreact-framage img {\n position: absolute;\n left: 0;\n top: 0;\n}",document.head.prepend(e)}function useFramageAnimation(e={frames:0,fps:0,orientation:"horizontal",step:0}){const{frames:a,initial:l,loop:o,fps:s,destroy:m,...c}=e??{},[g,h]=t(l??0),[f,d]=t(!1),u="number"==typeof a?a:a?.length??1,p=i(l??0),v=i(null);p.current=g;const b=n((()=>{if(!e)return;let t=o&&p.current+1>=u?0:p.current+1;if(p.current+1>=u&&c.onEnd?.(),t>=u&&(v.current&&clearInterval(v.current),m))return d(!0);0===t&&c.onStart?.(),c.onChange?.(t),h(t)}),[e]);r((()=>{if(h(l??0),d(!1),!e)return;if(c.onStart?.(),s<=0)return;const t=setInterval(b,1e3/s);return v.current=t,()=>clearInterval(t)}),[e?.key]);return[g,e?"number"==typeof e.frames?g:e.frames[g]:0,f]}function useFramageImage(e,t,i){function getImagePosition(e){let n=0;const r="left"===e?"horizontal":"vertical";i.animation&&i.animation.orientation===r&&(n=i.animation.step*i.steps);return(n+(i.view[e]??0))/t.current["left"===e?"naturalWidth":"naturalHeight"]*-100+"%"}function setImagePosition(){t.current&&(t.current.style.transform=`translate(${getImagePosition("left")}, ${getImagePosition("top")})`)}function getImageSize(n){const r=i.view[n];if(!e.current||!t.current||0===r)return"0";return e.current["width"===n?"clientWidth":"clientHeight"]/r*t.current["width"===n?"naturalWidth":"naturalHeight"]+"px"}function setImageSize(){t.current&&(t.current.style.width=getImageSize("width"),t.current.style.height=getImageSize("height"))}r(setImagePosition,[i.frame]);const n=new ResizeObserver(setImageSize);function handleImageLoad(){setImageSize(),setImagePosition()}r((()=>(t.current?.addEventListener("load",handleImageLoad),e.current&&n.observe(e.current),()=>{t.current?.removeEventListener("load",handleImageLoad),n.disconnect()})),[])}const o=a({frame:0,steps:0,imageProps:{}});function NineslicedFramage({view:t,animation:n,nineslice:a,...l}){const s=i(null),m=function parseNinesliceProp(e){return"number"==typeof e?{top:e,left:e,bottom:e,right:e}:{top:e.top??0,left:e.left??0,bottom:e.bottom??0,right:e.right??0}}(a),[c,g,h]=useFramageAnimation(n);r((()=>{s.current?.setFallbackSize(t.width,t.height,m)}),[t,h]);const f={"top-left":{width:m.left,height:m.top},"top-middle":{width:t.width-m.left-m.right,height:m.top,left:(t.left??0)+m.left},"top-right":{width:m.right,height:m.top,left:t.width-m.right},"middle-left":{width:m.left,height:t.height-m.top-m.bottom,top:(t.top??0)+m.top},middle:{width:t.width-m.left-m.right,height:t.height-m.top-m.bottom,left:(t.left??0)+m.left,top:(t.left??0)+m.top},"middle-right":{width:m.right,height:t.height-m.top-m.bottom,left:(t.left??0)+t.width-m.right,top:(t.top??0)+m.top},"bottom-left":{width:m.left,height:m.bottom,top:(t.top??0)+t.height-m.bottom},"bottom-middle":{width:t.width-m.left-m.right,height:m.bottom,left:(t.left??0)+m.left,top:(t.top??0)+t.height-m.bottom},"bottom-right":{width:m.right,height:m.bottom,left:t.width-m.right,top:(t.top??0)+t.height-m.bottom}};return h?null:e("react-framage",{ninesliced:!0,steps:n?g:void 0,frame:n?c:void 0,ref:s,children:e(o.Provider,{value:{frame:c,steps:g,animation:n,imageProps:l},children:Object.entries(f).map((([i,n])=>e(FramageSlice,{main:"middle"===i,view:{...t,...n}},i)))})})}function FramageSlice({view:t,main:n}){const{frame:r,steps:a,animation:s,imageProps:m}=l(o),c=i(null),g=i(null);return useFramageImage(c,g,{view:t,animation:s,frame:r,steps:a}),e("react-framage-slice",{"aria-hidden":!n||void 0,ref:c,children:e("img",{ref:g,...m})})}function RegularFramage({view:t,animation:n,...a}){const l=i(null),o=i(null),[s,m,c]=useFramageAnimation(n);return useFramageImage(l,o,{view:t,animation:n,frame:s,steps:m}),r((()=>{l.current?.setFallbackSize(t.width,t.height)}),[t,c]),c?null:e("react-framage",{steps:n?m:void 0,frame:n?s:void 0,ref:l,children:e("img",{ref:o,...a})})}function Framage({nineslice:t,...i}){return void 0===t?e(RegularFramage,{...i}):e(NineslicedFramage,{nineslice:t,...i})}class ReactFramageElement extends HTMLElement{get ninesliced(){return this.hasAttribute("ninesliced")}set ninesliced(e){e?this.setAttribute("ninesliced",""):this.removeAttribute("ninesliced")}setFallbackSize(e,t,i){if(this.style.setProperty("--fallback-width",e+"px"),this.style.setProperty("--fallback-height",t+"px"),i)for(const e in i){const t=i[e];this.style.setProperty(`--fallback-nineslice-${e}`,t+"px")}}}class ReactFramageSliceElement extends HTMLElement{}customElements.define("react-framage",ReactFramageElement),customElements.define("react-framage-slice",ReactFramageSliceElement);export{Framage,ReactFramageElement,ReactFramageSliceElement,Framage as default,useFramageAnimation,useFramageImage}; //# sourceMappingURL=index.js.map