likes
comments
collection
share

总有一种你会用的到-----vue大屏自适应解决方案

作者站长头像
站长
· 阅读数 17

我正在参加「掘金·启航计划」 bytedance.feishu.cn/docx/C6QQdS…

自适应的问题

  1. 屏幕像素大小不同,统一表现

  2. 画面比例不同,统一表现

  3. 浏览器字体最小限制,不可能无限等比缩小

  4. 画面出现拉伸压缩

  5. 文字内容显示异常

  6. 画面出现空白区域

一. css缩放方案: 利用transform:scale 进行适配

大屏自适应组件 v-scale-screen

v-scale-screen使用css属性transform实现缩放效果,进行等比例计算,达到等比例缩放的效果,同时我们也支持铺满全屏,宽度等比,高度等比,等自适应方案

值得注意: vue2请使用v-scale-screen@1.0.0版本, vue3请使用v-scale-screen@2.0.0版本

安装

npm install v-scale-screen -save # or yarn add v-scale-screen

vue2

// main.js
import Vue from "vue";

import App from "./App.vue";

// 引入 VScaleScreen

import VScaleScreen from "v-scale-screen";

Vue.use(VScaleScreen);

Vue.config.productionTip = false;

  
new Vue({

render: (h) => h(App)

}).$mount("#app");
<template>

<VScaleScreen>

<img src="" alt="" />

</VScaleScreen>

</template>

<script>

export default {

name: "home",

components: {},
};

</script>

<style>

* {

margin: 0;

padding: 0;

}

</style>

vue3

//main
import { createApp } from "vue";

import App from "./App.vue";

 
createApp(App).mount("#app");
<template>

<VScaleScreen>

<img src="" alt="" />

</VScaleScreen>

</template>

<script>

import VScaleScreen from "v-scale-screen";

export default {

name: "home",

components: {
VScaleScreen,

},

};
</script>
<style>

* {

margin: 0;

padding: 0;

}

</style>

二. rem方案

原理: 利用html的font-size变换,在移动端也经常使用此方法。 css 相对单位,相对于根元素的 font-size 值的大小 将设计稿的单位转化为rem单位就可以实现等比例的自适应缩放 随窗口变化响应地调整根元素font size

在utils目录下创建flexible.js, 复制下方代码。黏贴保存。


(function (win, lib) {
  var doc = win.document;
  var docEl = doc.documentElement;
  var metaEl = doc.querySelector('meta[name="viewport"]');
  var flexibleEl = doc.querySelector('meta[name="flexible"]');
  var dpr = 0;
  var scale = 0;
  var tid;
  var flexible = lib.flexible || (lib.flexible = {});
 
  if (metaEl) {
    console.warn("将根据已有的meta标签来设置缩放比例");
    var match = metaEl.getAttribute("content").match(/initial-scale=([d.]+)/);
    if (match) {
      scale = parseFloat(match[1]);
      dpr = parseInt(1 / scale);
    }
  } else if (flexibleEl) {
    var content = flexibleEl.getAttribute("content");
    if (content) {
      var initialDpr = content.match(/initial-dpr=([d.]+)/);
      var maximumDpr = content.match(/maximum-dpr=([d.]+)/);
      if (initialDpr) {
        dpr = parseFloat(initialDpr[1]);
        scale = parseFloat((1 / dpr).toFixed(2));
      }
      if (maximumDpr) {
        dpr = parseFloat(maximumDpr[1]);
        scale = parseFloat((1 / dpr).toFixed(2));
      }
    }
  }
 
  if (!dpr && !scale) {
    // var isAndroid = win.navigator.appVersion.match(/android/gi);
    var isIPhone = win.navigator.appVersion.match(/iphone/gi);
    var devicePixelRatio = win.devicePixelRatio;
    if (isIPhone) {
      // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
      if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
        dpr = 3;
      } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)) {
        dpr = 2;
      } else {
        dpr = 1;
      }
    } else {
      // 其他设备下,仍旧使用1倍的方案
      dpr = 1;
    }
    scale = 1 / dpr;
  }
 
  docEl.setAttribute("data-dpr", dpr);
  if (!metaEl) {
    metaEl = doc.createElement("meta");
    metaEl.setAttribute("name", "viewport");
    metaEl.setAttribute(
      "content",
      "initial-scale=" +
        scale +
        ", maximum-scale=" +
        scale +
        ", minimum-scale=" +
        scale +
        ", user-scalable=no"
    );
    if (docEl.firstElementChild) {
      docEl.firstElementChild.appendChild(metaEl);
    } else {
      var wrap = doc.createElement("div");
      wrap.appendChild(metaEl);
      doc.write(wrap.innerHTML);
    }
  }
 
  function refreshRem() {
    var width = docEl.getBoundingClientRect().width;
    if (width / dpr > 1920) {
      // 这个位置划重点 1920是设计稿的大小 如果你的设计稿是750 那么就需要将1920替换成750
      width = (docEl.clientWidth / 1920) * 1920;
    }
    var rem = width / 10;
    docEl.style.fontSize = rem + "px";
    flexible.rem = win.rem = rem;
  }
 
  win.addEventListener(
    "resize",
    function () {
      clearTimeout(tid);
      tid = setTimeout(refreshRem, 300);
    },
    false
  );
  win.addEventListener(
    "pageshow",
    function (e) {
      if (e.persisted) {
        clearTimeout(tid);
        tid = setTimeout(refreshRem, 300);
      }
    },
    false
  );
 
  if (doc.readyState === "complete") {
    doc.body.style.fontSize = 12 * dpr + "px";
  } else {
    doc.addEventListener(
      "DOMContentLoaded",
      function () {
        doc.body.style.fontSize = 12 * dpr + "px";
      },
      false
    );
  }
 
  refreshRem();
 
  flexible.dpr = win.dpr = dpr;
  flexible.refreshRem = refreshRem;
  flexible.rem2px = function (d) {
    var val = parseFloat(d) * this.rem;
    if (typeof d === "string" && d.match(/rem$/)) {
      val += "px";
    }
    return val;
  };
  flexible.px2rem = function (d) {
    var val = parseFloat(d) / this.rem;
    if (typeof d === "string" && d.match(/px$/)) {
      val += "rem";
    }
    return val;
  };
})(window, window["lib"] || (window["lib"] = {}));


在main.js中导入一下就行

import '@/utils/flexible'

利用vscode插件

cssrem

总有一种你会用的到-----vue大屏自适应解决方案

总有一种你会用的到-----vue大屏自适应解决方案

填写内容:

设计稿的宽度 * 0.1 = 填写的数字

1920 * 0.1 = 192

750 * 0.1 = 75

总有一种你会用的到-----vue大屏自适应解决方案

使用效果

总有一种你会用的到-----vue大屏自适应解决方案

三.postcss插件使用

postcss 一种对css编译的工具,类似babel对js的处理,通过它的插件生态来实现各种功能转换,如: autoprefixer(. 自动补全浏览器前缀), px2rem(自动将px转换为rem) 这里对px2rem配置说明如下: postcss-plugin-px2rem: 作为postcss的经典插件之一,用于自动转换px为rem postcss-px2rem文档

1.安装

npm i postcss-plugin-px2rem -D
  1. 配置vue.config.js
css: {
      loaderOptions: {
          postcss: {
              plugins: [
                  require('postcss-plugin-px2rem')({
                       rootValue: 100, //换算基数, 默认100  ,这样的话把根标签的字体规定为1rem为50px,这样就可以从设计稿上量出多少个px直接在代码中写多上px了。
                      unitPrecision: 5, //允许REM单位增长到的十进制数字。
                      propWhiteList: [],  //默认值是一个空数组,这意味着禁用白名单并启用所有属性。
                      propBlackList: [], //黑名单
                      exclude: /(node_module)/,  //默认false,可以(reg)利用正则表达式排除某些文件夹的方法,例如/(node_module)/ 。如果想把前端UI框架内的px也转换成rem,请把此属性设为默认值
                      selectorBlackList: [], //要忽略并保留为px的选择器
                      ignoreIdentifier: false,  //(boolean/string)忽略单个属性的方法,启用ignoreidentifier后,replace将自动设置为true。
                      replace: true, // (布尔值)替换包含REM的规则,而不是添加回退。
                      mediaQuery: false,  //(布尔值)允许在媒体查询中转换px。
                      minPixelValue: 3 //设置要替换的最小像素值(3px会被转rem)。 默认 0
                  }),
              ]
          }
      }
  },

转载自:https://juejin.cn/post/7227434605393231928
评论
请登录