| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- export interface IgnoreOption {
- el: string;
- height?: string;
- width?: string;
- scale?: number;
- fontSize?: number;
- }
- export interface AutofitOption {
- el?: string;
- dw?: number;
- dh?: number;
- resize?: boolean;
- ignore?: (IgnoreOption | string)[];
- transition?: number;
- delay?: number;
- limit?: number;
- cssMode?: "scale" | "zoom";
- allowScroll?: boolean;
- }
- declare interface Autofit {
- /**
- * 参数列表
- * 对象:
- *
- * @param {AutofitOption|String|undefined} options
- * @param {boolean|undefined} isShowInitTip
- * - 传入对象,对象中的属性如下:
- * - el(可选):渲染的元素,默认是 "body"
- * - dw(可选):设计稿的宽度,默认是 1920
- * - dh(可选):设计稿的高度,默认是 1080
- * - resize(可选):是否监听resize事件,默认是 true
- * - ignore(可选):忽略缩放的元素(该元素将反向缩放),参数见readme.md
- * - transition(可选):过渡时间,默认是 0
- * - delay(可选):延迟,默认是 0
- * - limit(可选):缩放限制,默认是 0.1
- * - cssMode(可选):缩放模式,默认是 scale,可选值有 scale 和 zoom, zoom 模式可能对事件偏移有利
- */
- init(options?: AutofitOption | string, isShowInitTip?: boolean): void;
- /**
- * @param {String} id
- * 关闭autofit.js造成的影响
- *
- */
- off(id?: string): void;
- /**
- * 检查autofit.js是否正在运行
- */
- isAutofitRunning: boolean;
- /**
- * @param {string} el - 待处理的元素选择器
- * @param {boolean} isKeepRatio - 是否保持纵横比(可选,默认为true,false时将充满父元素)
- * @param {number|undefined} level - 缩放等级,用于手动调整缩放程度(可选,默认为 1)
- */
- elRectification: typeof elRectification;
- /**
- * 当前缩放比例
- */
- scale: number
- }
- // type Ignore = Array<{ height: number, width: number, fontSize: number, scale: number, el: HTMLElement, dom: HTMLElement }>;
- let currRenderDom: string | HTMLElement = null!;
- let currelRectification = "";
- let currelRectificationLevel: string | number = "";
- let currelRectificationIsKeepRatio: string | boolean = "";
- let resizeListener: EventListenerOrEventListenerObject = null!;
- let timer: number = null!;
- let currScale: string | number = 1;
- let isElRectification = false;
- const autofit: Autofit = {
- isAutofitRunning: false,
- init(options = {}, isShowInitTip = true) {
- if (isShowInitTip) {
- console.log(`autofit.js is running`);
- }
- const {
- dw = 1920,
- dh = 1080,
- el = typeof options === "string" ? options : "body",
- resize = true,
- ignore = [],
- transition = "none",
- delay = 0,
- limit = 0.1,
- cssMode = "scale",
- allowScroll = false,
- } = options as AutofitOption;
- currRenderDom = el;
- const dom = document.querySelector<HTMLElement>(el);
- if (!dom) {
- console.error(`autofit: '${el}' is not exist`);
- return;
- }
- const style = document.createElement("style");
- const ignoreStyle = document.createElement("style");
- style.lang = "text/css";
- ignoreStyle.lang = "text/css";
- style.id = "autofit-style";
- ignoreStyle.id = "ignoreStyle";
- !allowScroll && (style.innerHTML = `body {overflow: hidden;}`);
- const bodyEl = document.querySelector("body")!;
- bodyEl.appendChild(style);
- bodyEl.appendChild(ignoreStyle);
- dom.style.height = `${dh}px`;
- dom.style.width = `${dw}px`;
- dom.style.transformOrigin = `0 0`;
- !allowScroll && (dom.style.overflow = "hidden");
- keepFit(dw, dh, dom, ignore, limit, cssMode);
- resizeListener = () => {
- clearTimeout(timer);
- if (delay != 0)
- timer = setTimeout(() => {
- keepFit(dw, dh, dom, ignore, limit, cssMode);
- isElRectification &&
- elRectification(currelRectification, currelRectificationIsKeepRatio, currelRectificationLevel);
- }, delay) as unknown as number;
- else {
- keepFit(dw, dh, dom, ignore, limit, cssMode);
- isElRectification &&
- elRectification(currelRectification, currelRectificationIsKeepRatio, currelRectificationLevel);
- }
- };
- resize && window.addEventListener("resize", resizeListener);
- this.isAutofitRunning = true;
- setTimeout(() => {
- dom.style.transition = `${transition}s`;
- });
- },
- off(el = "body") {
- try {
- window.removeEventListener("resize", resizeListener);
- const autofitStyle = document.querySelector("#autofit-style");
- autofitStyle && autofitStyle.remove();
- const ignoreStyleDOM = document.querySelector("#ignoreStyle");
- ignoreStyleDOM && ignoreStyleDOM.remove();
- const temp = document.querySelector<HTMLDivElement>(currRenderDom ? currRenderDom as string : el);
- temp && (temp.style.cssText = "")
- isElRectification && offelRectification();
- } catch (error) {
- console.error(`autofit: Failed to remove normally`, error);
- }
- this.isAutofitRunning = false;
- console.log(`autofit.js is off`);
- },
- elRectification: null!,
- scale: currScale
- };
- function elRectification(el: string, isKeepRatio: string | boolean = true, level: string | number = 1) {
- if (!autofit.isAutofitRunning) {
- console.error("autofit.js:(elRectification): autofit has not been initialized yet");
- return;
- }
- offelRectification();
- !el && console.error(`autofit.js:elRectification bad selector: ${el}`);
- currelRectification = el;
- currelRectificationLevel = level;
- currelRectificationIsKeepRatio = isKeepRatio;
- const currEl = Array.from(document.querySelectorAll<HTMLElement & { originalWidth: number, originalHeight: number }>(el));
- if (currEl.length == 0) {
- console.error(`autofit.js:elRectification found no element by selector: "${el}"`);
- return;
- }
- for (const item of currEl) {
- const rectification = currScale == 1 ? 1 : Number(currScale) * Number(level);
- if (!isElRectification) {
- item.originalWidth = item.clientWidth;
- item.originalHeight = item.clientHeight;
- }
- if (isKeepRatio) {
- item.style.width = `${item.originalWidth * rectification}px`;
- item.style.height = `${item.originalHeight * rectification}px`;
- } else {
- item.style.width = `${100 * rectification}%`;
- item.style.height = `${100 * rectification}%`;
- }
- item.style.transform = `translateZ(0) scale(${1 / Number(currScale)})`;
- item.style.transformOrigin = `0 0`;
- }
- isElRectification = true;
- }
- function offelRectification() {
- if (!currelRectification) return;
- isElRectification = false;
- for (const item of Array.from(document.querySelectorAll<HTMLElement>(currelRectification))) {
- item.style.width = ``;
- item.style.height = ``;
- item.style.transform = ``;
- }
- }
- function keepFit(
- dw: number,
- dh: number,
- dom: HTMLElement,
- ignore: AutofitOption['ignore'],
- limit: number,
- cssMode: AutofitOption['cssMode'] = "scale"
- ) {
- const clientHeight = document.documentElement.clientHeight;
- const clientWidth = document.documentElement.clientWidth;
- currScale =
- clientWidth / clientHeight < dw / dh ? clientWidth / dw : clientHeight / dh;
- currScale = Math.abs(1 - currScale) > limit ? currScale : 1;
- autofit.scale = +currScale;
- const height = Math.round(clientHeight / Number(currScale));
- const width = Math.round(clientWidth / Number(currScale));
- dom.style.height = `${height}px`;
- dom.style.width = `${width}px`;
- if (cssMode === "zoom") {
- (dom.style as any).zoom = `${currScale}`;
- } else {
- dom.style.transform = `translateZ(0) scale(${currScale})`;
- }
- const ignoreStyleDOM = document.querySelector("#ignoreStyle")!;
- ignoreStyleDOM.innerHTML = "";
- for (const temp of ignore!) {
- const item = temp as IgnoreOption & { dom: string };
- let itemEl = item.el || item.dom;
- typeof item == "string" && (itemEl = item);
- if (!itemEl || (typeof itemEl === "object" && !Object.keys(itemEl).length)) {
- console.error(`autofit: found invalid or empty selector/object: ${itemEl}`);
- continue;
- }
- const realScale: number = item.scale ? item.scale : 1 / Number(currScale);
- const realFontSize = realScale != currScale && item.fontSize;
- const realWidth = realScale != currScale && item.width;
- const realHeight = realScale != currScale && item.height;
- ignoreStyleDOM.innerHTML += `\n${itemEl} {
- transform: scale(${realScale})!important;
- transform-origin: 0 0;
- ${realWidth ? `width: ${realWidth}!important;` : ''}
- ${realHeight ? `height: ${realHeight}!important;` : ''}
- }`;
- if (realFontSize) {
- ignoreStyleDOM.innerHTML += `\n${itemEl} div ,${itemEl} span,${itemEl} a,${itemEl} * {
- font-size: ${realFontSize}px;
- }`;
- }
- }
- }
- autofit.elRectification = elRectification;
- export { autofit as default, elRectification };
|