vue pc端-移动端-ipad端适配

全局使用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
  1. 在上述代码的基础上添加下述代码
// 定义一个需要额外添加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.clientHeight
  let clientWidth = document.documentElement.clientWidth
  currScale =
    clientWidth / clientHeight < dw / dh ? clientWidth / dw : clientHeight / dh
    for(let k = 0; k<dom.length;k++) {
      dom[k].style.transform = `scale(${currScale})`
    }
  
}
  1. 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);
     }
   };

你可能感兴趣的:(vue.js,前端,javascript)