全局使用transform:scale来进行适配
在utils下创建js文件,比如命名为:autofit.js
let currRenderDom = null;
let currelRectification = "";
let currelRectificationLevel = "";
let resizeListener = null;
let timer = null;
let currScale = 1;
let isAutofitRunnig = false;
let isElRectification = false;
let keyboardHeight = 0;const autofit = {init(options = {}, isShowInitTip = true) {if (isShowInitTip) {console.log(`%c` + `autofit.js` + ` is running`,`font-weight: bold; color: #ffb712; background:linear-gradient(-45deg, #bd34fe 50%, #47caff 50% );background: -webkit-linear-gradient( 120deg, #bd34fe 30%, #41d1ff );background-clip: text;-webkit-background-clip: text; -webkit-text-fill-color:linear-gradient( -45deg, #bd34fe 50%, #47caff 50% ); padding: 8px 12px; border-radius: 4px;`);console.log(options.dw);}const {dw = 1920,dh = 929,el = typeof options === "string" ? options : "#app",resize = true,ignore = [],transition = "none",delay = 0,} = options;currRenderDom = el;let dom = document.querySelector(el);if (!dom) {console.error(`autofit: '${el}' is not exist`);return;}defaultHeight = document.documentElement.clientHeight;defaultWidth = document.documentElement.clientWidth;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";style.innerHTML = `body {overflow: hidden;}`;dom.appendChild(style);dom.appendChild(ignoreStyle);dom.style.height = `${dh}px`;dom.style.width = `${dw}px`;dom.style.transformOrigin = `0 0`;keepFit(dw, dh, dom, ignore);resizeListener = () => {clearTimeout(timer);if (delay != 0)timer = setTimeout(() => {keepFit(dw, dh, dom, ignore);isElRectification &&elRectification(currelRectification, currelRectificationLevel);}, delay);else {keepFit(dw, dh, dom, ignore);isElRectification &&elRectification(currelRectification, currelRectificationLevel);}};resize && window.addEventListener("resize", resizeListener);isAutofitRunnig = true;setTimeout(() => {dom.style.transition = `${transition}s`;});},off(el = "#app") {try {isElRectification = false;window.removeEventListener("resize", resizeListener);document.querySelector("#autofit-style").remove();document.querySelector(currRenderDom ? currRenderDom : el).style = "";isElRectification && offelRectification();} catch (error) {console.error(`autofit: Failed to remove normally`, error);isAutofitRunnig = false;}isAutofitRunnig &&console.log(`%c` + `autofit.js` + ` is off`,`font-weight: bold;color: #707070; background: #c9c9c9; padding: 8px 12px; border-radius: 4px;`);},
};function elRectification(el, level = 1) {if (!isAutofitRunnig) {console.error("autofit.js:autofit has not been initialized yet");}!el && console.error(`autofit.js:bad selector: ${el}`);currelRectification = el;currelRectificationLevel = level;const currEl = document.querySelectorAll(el);if (currEl.length == 0) {console.error("autofit.js:elRectification found no element");return;}for (let item of currEl) {if (!isElRectification) {item.originalWidth = item.clientWidth;item.originalHeight = item.clientHeight;}let rectification = currScale == 1 ? 1 : currScale * level;item.style.width = `${item.originalWidth * rectification}px`;item.style.height = `${item.originalHeight * rectification}px`;item.style.transform = `scale(${1 / currScale})`;item.style.transformOrigin = `0 0`;}isElRectification = true;
}
function offelRectification() {if (!currelRectification) return;for (let item of document.querySelectorAll(currelRectification)) {item.style.width = ``;item.style.height = ``;item.style.transform = ``;}
}
function keepFit(dw, dh, dom, ignore) {let clientHeight = document.documentElement.clientHeight;let clientWidth = document.documentElement.clientWidth;currScale =clientWidth / clientHeight < dw / dh ? clientWidth / dw : clientHeight / dh;dom.style.height = `${clientHeight / currScale}px`;dom.style.width = `${clientWidth / currScale}px`;dom.style.transform = `scale(${currScale})`;for (let item of ignore) {let itemEl = item.el || item.dom;typeof item == "string" && (itemEl = item);if (!itemEl) {console.error(`autofit: bad selector: ${itemEl}`);continue;}let realScale = item.scale ? item.scale : 1 / currScale;let realFontSize = realScale != currScale ? item.fontSize : "autofit";let realWidth = realScale != currScale ? item.width : "autofit";let realHeight = realScale != currScale ? item.height : "autofit";let regex = new RegExp(`${itemEl}(\x20|{)`, "gm");let isIgnored = regex.test(document.querySelector("#ignoreStyle").innerHTML);if (isIgnored) {continue;}document.querySelector("#ignoreStyle").innerHTML += `\n${itemEl} { transform: scale(${realScale})!important;transform-origin: 0 0;width: ${realWidth}!important;height: ${realHeight}!important;}`;document.querySelector("#ignoreStyle").innerHTML += `\n${itemEl} div ,${itemEl} span,${itemEl} a,${itemEl} * {font-size: ${realFontSize}px;}`;}
}
export { elRectification };
export default autofit;
在App.vue中引入使用
import autofit from "@/utils/autofit";
autofit.init({dh: 1080,dw: 1920,el: "#app",resize: true,
});
如果想要某个不在上述设置的el下的dom也使用响应式,添加transform
- 在上述代码的基础上添加下述代码
// 定义一个需要额外添加transform的属性默认为false
let hasFlag = false
// 在init方法中的options额外添加一个参数needScaleClass
const {dw = 1920,dh = 929,el = typeof options === 'string' ? options : '#app',resize = true,ignore = [],transition = 'none',delay = 0,needScaleClass = ''} = options// 然后获取当前所有类名为needScaleClass的dom(init方法中)
let scaleDom = document.querySelectorAll(needScaleClass)if (scaleDom) {hasFlag = true}if (hasFlag) {needScaleDom(dw, dh, scaleDom)}// resize监听中调用方法resizeListener = () => {clearTimeout(timer)if (delay != 0)timer = setTimeout(() => {keepFit(dw, dh, dom, ignore)if (hasFlag) {needScaleDom(dw, dh, scaleDom)}isElRectification &&elRectification(currelRectification, currelRectificationLevel)}, delay)else {keepFit(dw, dh, dom, ignore)if (hasFlag) {needScaleDom(dw, dh, scaleDom)}isElRectification &&elRectification(currelRectification, currelRectificationLevel)}}setTimeout(() => {dom.style.transition = `${transition}s`if (hasFlag) {for(let m = 0; m<scaleDom.length;m++) {scaleDom[m].style.transition = `${transition}s`}}})//添加方法给dom赋值style
function needScaleDom (dw, dh, dom) {let clientHeight = document.documentElement.clientHeightlet clientWidth = document.documentElement.clientWidthcurrScale =clientWidth / clientHeight < dw / dh ? clientWidth / dw : clientHeight / dhfor(let k = 0; k<dom.length;k++) {dom[k].style.transform = `scale(${currScale})`}}
- App.vue中使用
import autofit from "@/utils/autofit";
autofit.init({dh: 1080,dw: 1920,el: "#app",resize: true,needScaleClass: '.message-toolip-box',
});
在移动端的使用
在移动端的时候,如果又要输入内容的时候键盘弹起会导致可视页面变小,就会触发resize监听从而改变scale的值,但是如果我们在输入内容时不想改变页面大小想保持原状,上述代码需要添加键盘弹起判断了
// 全局定义默认宽高
let defaultHeight = 0;
let defaultWidth = 0;
// 在resize监听中
resizeListener = () => {const windowHeight = window.innerHeight;const windowWidth = window.innerWidth;// 如果当前窗口高度小于默认高度,且宽度和默认宽度相等则说明键盘是打开状态let keyboardHeight = defaultHeight - windowHeight;if (keyboardHeight > 0 && windowWidth == defaultWidth) {let transform = dom.style.transform;const result = transform.slice(0, transform.indexOf(")") + 1);let a = "translateY(-" + keyboardHeight + "px)";dom.style.transform = result + a;return;}// 宽度和默认宽度不相等,可能是切换了不同分辨率或者变为了横屏状态if (windowWidth != defaultWidth) {defaultHeight = document.documentElement.clientHeight;defaultWidth = document.documentElement.clientWidth;}clearTimeout(timer);if (delay != 0)timer = setTimeout(() => {keepFit(dw, dh, dom, ignore);isElRectification &&elRectification(currelRectification, currelRectificationLevel);}, delay);else {keepFit(dw, dh, dom, ignore);isElRectification &&elRectification(currelRectification, currelRectificationLevel);}};