vue3+ts+vite数据大屏自适应总结(两种方法)

总结一下我常用的数据大屏自适应方法

1、通过css缩放方案: 利用transform:scale 进行适配

我一般使用 v-scale-screen 插件
主要用于同比例缩放,例如16:9(1k,2k,4k)

vue2版本(npm官网):https://www.npmjs.com/package/vue2-scale-box
vue3版本(npm官网):https://www.npmjs.com/package/vue3-scale-box

yarn add vue3-scale-box

<template>
  <ScaleBox
    :width="1920"
    :height="1080"
    bgc="transparent"
    :delay="100"
    :isFlat="false"
  >
    <div class="ec-demo" id="ec-demo"></div>
  </ScaleBox>
</template>
<script setup>
import ScaleBox from "vue3-scale-box";
</script>

2、采用rem布局, 根据屏幕分辨率大小不同,调整根元素html的font-size, 从而达到每个元素宽高自动变化,适配不同屏幕

我一般使用 postcss-pxtorem + lib-flexible 插件
主要用于多个不同比例缩放,例如16:9(1k,2k,4k),21:9或其他比例
适配的方法总体分为两步:

  1. px转换成rem
  2. rem根据屏幕大小重置基数改变大小

2.1、先下载postcss-pxtorem

yarn add postcss-pxtorem 

"postcss-pxtorem": "^6.0.0",

2.2、在vite.config.ts配置

import postcssPxtoRem from "postcss-pxtorem";

css: {
  postcss: {
    plugins: [
      postcssPxtoRem({
        rootValue: 192, // 按照自己的设计稿修改 1920/10
        unitPrecision: 5, // 保留到5位小数
        selectorBlackList: ["ignore"], // 忽略转换正则匹配项
        propList: ["*", "!border"],
        replace: true,
        mediaQuery: false, // 媒体查询( @media screen 之类的)中不生效
        minPixelValue: 1, //可以选择px小于1的不会被转换
      }),
    ],
  },
},

2.3、在src/utils下创建flexible.js文件(lib-flexible插件建议放到本地)

因为我要适配不同比例的大屏,我把lib-flexible插件放在了本地(方便修改)

可以在 refreshRem() 方法中对不同分辨率进行设置

(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 || isAndroid) {
      // 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 = devicePixelRatio;
    }
    scale = 1 / dpr;
    // 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;
    var height = docEl.getBoundingClientRect().height;

    if (width / dpr < 1600) {
      width = 1920 * dpr;
    }
    var rem = (width * dpr) / 10;
    docEl.style.fontSize = rem + "px";
    flexible.rem = win.rem = rem;
    // if(width>3040&&width<3640){
    //   docEl.style.fontSize = 1 + "px";
    //   flexible.rem = 1 + "px";
    // }
  }
  win.addEventListener(
    "resize",
    function () {
      refreshRem();
    },
    false
  );
  win.addEventListener(
    "pageshow",
    function (e) {
      if (e.persisted) {
        refreshRem();
      }
    },
    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"] = {}));

2.4、在main.js中引入flexible.js

//px转rem
// 使用下面@ts-ignore表示忽略ts类型检测,否则下面代码打包时会报错
import '@/utils/flexible.js'

2.5、注意事项

1、 框架组件和标签中直接定义的 width和height进行不了转换, 例如img标签
2、 大多框架只适配1920*1080的,其他比例,框架组件可能会变形,需要单独设置,可以在全局css文件进行修改。

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值