屏幕適配的兩種方案,超詳細!

作者:瀟瀟夜雨丶

https://juejin.cn/post/7147897102398390308

前言

最近項目組小美同學貌似遇到了一個棘手的問題,總是一副悶悶不樂的樣子。

本着都是一個項目組,應該互相幫助、共用解決問題的用意,我向小美髮出了信息。

我:“看你最近一直不怎麼開心,遇到什麼問題了嗎?”

小美:“最近一直在查閱 vue3 項目屏幕適配的資料,發現網上資料都是 vue2+webpack 有關的,不知道如何適配 vite 項目?o(╥﹏╥)o”

我:“OK,交給哥了,我來幫你擺平!”

小美:“❤( ´・ᴗ・`)❤”

基於 rem 的適配方案

rem 是什麼?

rem 是指相對於根元素的字體大小的單位,在日常開發過程中我們通常把根元素(html/body)的字體設置爲 10px, 方便於我們計算(此時子元素的 1rem 就相當於 10px)。

適用場景

不固定寬高比的 Web 應用,適用於絕大部分業務場景

項目實戰

  1. 安裝依賴
npm i postcss-pxtorem autoprefixer amfe-flexible --save-dev

postcss-pxtorem 是 PostCSS 的插件,用於將像素單元生成 rem 單位 autoprefixer 瀏覽器前綴處理插件 amfe-flexible 可伸縮佈局方案 替代了原先的lib-flexible 選用了當前衆多瀏覽器兼容的viewport

  1. 項目根目錄創建 postcss.config.js 文件

module.exports = {
 plugins: {
  autoprefixer: {
   overrideBrowserslist: [
    "Android 4.1",
    "iOS 7.1",
    "Chrome > 31",
    "ff > 31",
    "ie >= 8",
    "last 10 versions", // 所有主流瀏覽器最近10版本用
   ],
   grid: true,
  },
  "postcss-pxtorem"{
   rootValue: 192, // 設計稿寬度的1/ 10 例如設計稿按照 1920設計 此處就爲192
   propList: ["*""!border"], // 除 border 外所有px 轉 rem
   selectorBlackList: [".el-"], // 過濾掉.el-開頭的class,不進行rem轉換
  },
 },
};
  1. main.ts/js 文件中導入依賴
import "amfe-flexible/index.js";
  1. 項目重啓

基於 scale 的適配方案

在 CSS3 中,我們可以使用 transform 屬性的 scale()方法來實現元素的縮放效果。縮放,指的是 “縮小” 和“放大”的意思。

適用場景

固定寬高比的 Web 應用,如大屏或者固定窗口業務應用

項目實戰

  1. 新建resize.ts/js文件

import { ref } from "vue";

export default function windowResize() {
 // * 指向最外層容器
 const screenRef = ref();
 // * 定時函數
 const timer = ref(0);
 // * 默認縮放值
 const scale = {
  width: "1",
  height: "1",
 };
    
 // * 設計稿尺寸(px)
 const baseWidth = 1920;
 const baseHeight = 1080;

 // * 需保持的比例(默認1.77778)
 const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5));
 const calcRate = () ={
  // 當前寬高比
  const currentRate = parseFloat(
   (window.innerWidth / window.innerHeight).toFixed(5)
  );
  if (screenRef.value) {
   if (currentRate > baseProportion) {
    // 表示更寬
    scale.width = (
     (window.innerHeight * baseProportion) /
     baseWidth
    ).toFixed(5);
    scale.height = (window.innerHeight / baseHeight).toFixed(5);
    screenRef.value.style.transform = `scale(${scale.width}${scale.height})`;
   } else {
    // 表示更高
    scale.height = (
     window.innerWidth /
     baseProportion /
     baseHeight
    ).toFixed(5);
    scale.width = (window.innerWidth / baseWidth).toFixed(5);
    screenRef.value.style.transform = `scale(${scale.width}${scale.height})`;
   }
  }
 };

 const resize = () ={
  clearTimeout(timer.value);
  timer.value = window.setTimeout(() ={
   calcRate();
  }, 200);
 };

 // 改變窗口大小重新繪製
 const windowDraw = () ={
  window.addEventListener("resize", resize);
 };

 // 改變窗口大小重新繪製
 const unWindowDraw = () ={
  window.removeEventListener("resize", resize);
 };

 return {
  screenRef,
  calcRate,
  windowDraw,
  unWindowDraw,
 };
}
  1. 相關界面引入resize.ts/js

<template>
    <div class="screen-container">
        <div class="screen-content" ref="screenRef">
            <span class="screen-title">基於scale的適配方案</span>
            <img class="screen-img" src="https://img2.baidu.com/it/u=1297807229,3828610143&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=281" alt="">
        </div>
    </div>
</template>

<script setup lang="ts">
import windowResize from '../../utils/resize';
import {onMounted, onUnmounted} from 'vue';

const { screenRef, calcRate, windowDraw, unWindowDraw } = windowResize()

onMounted(() ={
    // 監聽瀏覽器窗口尺寸變化
    windowDraw()
    calcRate()
})

onUnmounted(() ={
    unWindowDraw();
})

</script>

<style lang="scss" scoped>
.screen-container {
    height: 100%;
    background-color: lightcyan;
    display: flex;
    justify-content: center;
    align-items: center;

    .screen-content {
        width: 1920px;
        height: 1080px;
        background-color: #fff;
        display: flex;
        justify-content: center;
        align-items: center;
        flex-direction: column;

        .screen-title {
            font-size: 32px;
        }

        .screen-img {
            margin-top: 20px;
        }
    }
}
</style>
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/jxxWkpR-W78FJp64By8pNg