大屏适配-vm和vh

概述

最近接到要做大屏首页的需求,要适配不同屏幕缩放比例合适,目前的大屏适配方案很多,如下是实际项目采用的方案vm+vh

实现思路

按照设计稿的尺寸,将px按比例计算转为vwvh,转换公式如下

scss 复制代码
假设设计稿尺寸为 1920*1080(做之前一定问清楚 ui 设计稿的尺寸)

即:
网页宽度=1920px
网页高度=1080px

我们都知道
网页宽度=100vw
网页宽度=100vh

所以,在 1920px*1080px 的屏幕分辨率下

1920px = 100vw

1080px = 100vh

这样一来,以一个宽 300px 和 200px 的 div 来说,其所占的宽高,以 vw 和 vh 为单位,计算方式如下:

vwDiv = (300px / 1920px ) * 100vw
vhDiv = (200px / 1080px ) * 100vh

所以,就在 1920*1080 的屏幕分辨率下,计算出了单个 div 的宽高

当屏幕放大或者缩小时,div 还是以 vw 和 vh 作为宽高的,就会自动适应不同分辨率的屏幕
复制代码

新建util.scss

scss 复制代码
@use "sass:math";

// 默认设计稿的宽度
$designWidth: 1920;
// 默认设计稿的高度
$designHeight: 1080;

// px 转为 vw 的函数
@function vw($px) {
  @return math.div($px, $designWidth) * 100vw;
}

// px 转为 vh 的函数
@function vh($px) {
  @return math.div($px, $designHeight) * 100vh;
}

vite配置

js 复制代码
//vite.config.js
import { defineConfig,
  
  type AliasOptions 

} from 'vite'
import { fileURLToPath, URL } from 'node:url'
import UnoCSS from 'unocss/vite'
import vue from '@vitejs/plugin-vue'
const alias: AliasOptions = {
  '@/my-vue-app': fileURLToPath(new URL('../../my-vue-app/src/main.js', import.meta.url)),
  "@": fileURLToPath(new URL('./src', import.meta.url)),
}

// https://vite.dev/config/
export default defineConfig({
  plugins: [vue(), UnoCSS()],
  resolve: {
    alias: {
      ...alias,
    },
  },
  
  css: {
    preprocessorOptions:{
      scss:{
        additionalData: `@use "@/style/util.scss" as *;  @use "@/style/element-variables.scss" as *; `, // 替换为你的实际文件路径
      }
    }
  },
})

使用

上面vite配置完成后即可项目全局使用计算样式

scss 复制代码
<style lang="scss">
.box{
    width: vw(800);
    height: vh(400);
    font-size: vh(16);
    background-color: pink;
    margin-left: vw(10);
    margin-top: vh(10);
    border: vh(2) solid red;
    font-size: 20px;
    border: 20px solid red;
  }
</style>

存在的问题

  • 上面的能处理我们项目自行写的样式,但是组件库内部的尺寸都是使用的scss变量,因此无法转化组件库内部的样式,解决办法就是将对应组件库的尺寸样式变量重写
  • echarts相关图标通过配置式传入的尺寸无法变动
  • 其他库里面写死的样式,没法改

解决组件库的问题

新建element-variables.scss,我以elementplus为例

scss 复制代码
注意:这里不能像外面项目那样使用vm()和vh()函数,编译会报错,这里自动根据尺寸高计算好变量覆盖element样式即可
// 覆盖 Element Plus 的默认变量
@forward "element-plus/theme-chalk/src/common/var.scss" with (
  // 修改默认尺寸变量(原本是 px,改成 vw/vh)
  $button-padding-vertical: 0.2vw,
  $button-padding-horizontal:0.4vw,
  $input-height: 0.3vw,
  // 其他需要修改的变量...
);

vite.config.js配置

js 复制代码
// https://vite.dev/config/
export default defineConfig({
  plugins: [vue(), UnoCSS()],
  resolve: {
    alias: {
      ...alias,
    },
  },
  
  css: {
    preprocessorOptions:{
      scss:{
        additionalData: `@use "@/style/util.scss" as *;  @use "@/style/element-variables.scss" as *; `, // 替换为你的实际文件路径
      }
    }
  },
})

问题2解决方案

2的问题其实也很简单,提取成函数,配置echarts相关属性的时候,将尺寸通过函数计算后传入即可,然后页面尺寸变化,重新调整echarts的尺寸即可 3的问题,我们借助postcss即可强制转化页面所有单位

问题3解决方案

对应非本项目其他库的组件的写死的样式,我们可以直接通过postscss在打包编译的时候,强制替换计算即可,下载postcss-px-to-viewport,然后新增postcss.config.js

js 复制代码
module.exports = {
    plugins: {
      "postcss-px-to-viewport": {
        unitToConvert: "px",
        viewportWidth: 1920, // 设计稿宽度
        viewportHeight: 1080, // 设计稿高度
        unitPrecision: 5,
        propList: ["*"], // 所有属性都转换
        viewportUnit: "vw",
        fontViewportUnit: "vw",
        selectorBlackList: [], // 不转换的选择器
        minPixelValue: 1,
        mediaQuery: false,
        replace: true,
        exclude: [/node_modules/], // 不转换 node_modules(避免影响 Element Plus)
      },
    },
  };

总结

上面的大屏方案不一定完全覆盖全部场景,可以根据自己项目需要,在做优化细节处理

相关推荐
一斤代码2 小时前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
中微子2 小时前
React Router 源码深度剖析解决面试中的深层次问题
前端·react.js
光影少年2 小时前
从前端转go开发的学习路线
前端·学习·golang
中微子2 小时前
React Router 面试指南:从基础到实战
前端·react.js·前端框架
3Katrina2 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
前端_学习之路3 小时前
React--Fiber 架构
前端·react.js·架构
伍哥的传说3 小时前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js
qq_424409194 小时前
uniapp的app项目,某个页面长时间无操作,返回首页
前端·vue.js·uni-app
我在北京coding4 小时前
element el-table渲染二维对象数组
前端·javascript·vue.js
布兰妮甜4 小时前
Vue+ElementUI聊天室开发指南
前端·javascript·vue.js·elementui