UNPKG

@scqilin/screen-scaler

Version:

A powerful screen scaling adapter for big screen applications with TypeScript support

2 lines (1 loc) 6.79 kB
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ScreenScaler={})}(this,function(e){"use strict";function t(){const e=document.createElement("div");e.style.cssText="width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;",document.body.appendChild(e);const t=e.offsetWidth-e.clientWidth;return document.body.removeChild(e),t}let i=t()+1;class s{constructor(e){this.rafId=null,this.isDestroyed=!1,this.validateConfig(e);const t="string"==typeof e.container?document.querySelector(e.container):e.container;if(!t)throw new Error("Container element not found");this.container=t,this.setupContainerStructure(),this.config={container:this.container,designWidth:e.designWidth,designHeight:e.designHeight,mode:e.mode||"auto",autoResize:!1!==e.autoResize,onScaleChange:e.onScaleChange||(()=>{})},this.resizeHandler=this.handleResize.bind(this),this.init()}setupContainerStructure(){this.parentContainer=this.container.parentElement||document.body,this.wrapperContainer=document.createElement("div"),this.wrapperContainer.className="screen-scaler-wrapper",Object.assign(this.wrapperContainer.style,{position:"relative",width:"100%",height:"100%"}),this.parentContainer.insertBefore(this.wrapperContainer,this.container),this.wrapperContainer.appendChild(this.container)}validateConfig(e){if(!e.container)throw new Error("Container is required");if(!e.designWidth||e.designWidth<=0)throw new Error("designWidth must be a positive number");if(!e.designHeight||e.designHeight<=0)throw new Error("designHeight must be a positive number")}init(){this.setupContainerStyles(),this.config.autoResize&&this.setupResizeObserver(),this.handleResize()}setupResizeObserver(){window.addEventListener("resize",this.resizeHandler)}setupContainerStyles(){const{designWidth:e,designHeight:t}=this.config;Object.assign(this.container.style,{width:`${e}px`,height:`${t}px`,transformOrigin:"0 0",position:"relative",margin:"0",padding:"0",border:"none",boxSizing:"border-box"})}handleResize(){this.isDestroyed||(this.rafId&&cancelAnimationFrame(this.rafId),this.rafId=requestAnimationFrame(()=>{setTimeout(()=>{this.setScale()},100)}))}getScreenSize(){this.wrapperContainer.offsetHeight;const e=this.wrapperContainer.style.overflow;this.wrapperContainer.style.overflow="hidden",this.wrapperContainer.offsetHeight;let t=this.wrapperContainer.clientWidth,i=this.wrapperContainer.clientHeight;return this.wrapperContainer.style.overflow=e,t<=0&&(t=window.innerWidth),i<=0&&(i=window.innerHeight),{width:t,height:i}}resetStyles(){Object.assign(this.container.style,{transform:"none",position:"relative",left:"0px",top:"0px"})}scaleNone(){const{designWidth:e,designHeight:t}=this.config,i=this.getScreenSize();return this.resetStyles(),{mode:"none",scale:{x:1,y:1,ratio:1},screen:i,design:{width:e,height:t},scaled:{width:e,height:t},offset:{x:0,y:0}}}scaleAuto(){const{designWidth:e,designHeight:t}=this.config,i=this.getScreenSize();this.resetStyles(),this.wrapperContainer.style.overflow="hidden";const s=i.width/e,n=i.height/t,r=Math.min(s,n),o=e*r,h=t*r,a=(i.width-o)/2,d=(i.height-h)/2;return Object.assign(this.container.style,{transform:`scale(${r})`,position:"absolute",left:`${a}px`,top:`${d}px`}),{mode:"auto",scale:{x:r,y:r,ratio:r},screen:i,design:{width:e,height:t},scaled:{width:o,height:h},offset:{x:a,y:d}}}scaleWidth(){const{designWidth:e,designHeight:t}=this.config;this.resetStyles();const s=this.getScreenSize();let n=s.width;e/t<s.width/s.height&&(n-=i);const r=n/e,o=e*r,h=t*r;this.container.style.transform=`scale(${r})`,this.wrapperContainer.style.overflowX="clip";let a=0;return h<=s.height?(a=Math.floor((s.height-h)/2),Object.assign(this.container.style,{position:"absolute",left:"0px",top:`${a}px`})):Object.assign(this.container.style,{position:"relative",left:"0px",top:"0px"}),{mode:"width",scale:{x:r,y:r,ratio:r},screen:s,design:{width:e,height:t},scaled:{width:o,height:h},offset:{x:0,y:a}}}scaleHeight(){const{designWidth:e,designHeight:t}=this.config;this.resetStyles();const s=this.getScreenSize();let n=s.height;e/t>s.width/s.height&&(n-=i);const r=n/t,o=e*r,h=t*r;this.container.style.transform=`scale(${r})`,this.wrapperContainer.style.overflowY="clip";let a=0;return o<=s.width?(a=Math.floor((s.width-o)/2),Object.assign(this.container.style,{position:"absolute",left:`${a}px`,top:"0px"})):Object.assign(this.container.style,{position:"relative",left:"0px",top:"0px"}),{mode:"height",scale:{x:r,y:r,ratio:r},screen:s,design:{width:e,height:t},scaled:{width:o,height:h},offset:{x:a,y:0}}}scaleStretch(){const{designWidth:e,designHeight:t}=this.config,i=this.getScreenSize();this.resetStyles(),this.wrapperContainer.style.overflow="hidden";const s=i.width/e,n=i.height/t;return Object.assign(this.container.style,{transform:`scaleX(${s}) scaleY(${n})`,position:"absolute",left:"0px",top:"0px"}),{mode:"stretch",scale:{x:s,y:n,ratio:Math.min(s,n)},screen:i,design:{width:e,height:t},scaled:{width:i.width,height:i.height},offset:{x:0,y:0}}}setScale(){if(this.isDestroyed)throw new Error("ScreenScaler has been destroyed");let e;switch(i=t()+1,this.config.mode){case"none":e=this.scaleNone();break;case"auto":e=this.scaleAuto();break;case"width":e=this.scaleWidth();break;case"height":e=this.scaleHeight();break;case"stretch":e=this.scaleStretch();break;default:throw new Error(`Unknown scale mode: ${this.config.mode}`)}return this.config.onScaleChange(e),e}setMode(e){if(this.isDestroyed)throw new Error("ScreenScaler has been destroyed");return this.config.mode=e,this.setScale()}getMode(){return this.config.mode}getScaleInfo(){return this.setScale()}updateDesignSize(e,t){if(this.isDestroyed)throw new Error("ScreenScaler has been destroyed");return this.config.designWidth=e,this.config.designHeight=t,this.setupContainerStyles(),this.setScale()}setAutoResize(e){if(this.isDestroyed)throw new Error("ScreenScaler has been destroyed");e&&!this.config.autoResize?this.setupResizeObserver():!e&&this.config.autoResize&&window.removeEventListener("resize",this.resizeHandler),this.config.autoResize=e}setOnScaleChange(e){this.config.onScaleChange=e}destroy(){this.isDestroyed||(window.removeEventListener("resize",this.resizeHandler),this.rafId&&(cancelAnimationFrame(this.rafId),this.rafId=null),Object.assign(this.container.style,{transform:"",position:"",left:"",top:"",width:"",height:""}),this.wrapperContainer&&this.wrapperContainer.parentElement&&(this.wrapperContainer.parentElement.insertBefore(this.container,this.wrapperContainer),this.wrapperContainer.remove()),this.isDestroyed=!0)}isDestroyed_(){return this.isDestroyed}}e.ScreenScaler=s,e.default=s,Object.defineProperty(e,"__esModule",{value:!0})});