大屏适配-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)
      },
    },
  };

总结

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

相关推荐
gongzemin12 分钟前
前端根据文件流渲染 PDF 和 DOCX 文件
前端·vue.js·express
jsonchao33 分钟前
大厂失业后,我用cursor开发了第二款海外产品
前端·程序员
gnip43 分钟前
低代码平台自定义组件实现思路
前端·低代码
实习生小黄1 小时前
基于扫描算法获取psd图层轮廓
前端·javascript·算法
青松学前端1 小时前
你不知道的秘密-axios源码
前端·javascript
GISer_Jing1 小时前
IntersectionObserver API&应用场景&示例代码详解
前端·javascript
未来之窗软件服务1 小时前
学校住宿缴费系统h5-——东方仙盟——仙盟创梦IDE
前端·javascript·ide·仙盟创梦ide·东方仙盟
markyankee1011 小时前
JavaScript 作用域与闭包详解
前端·javascript
gufs镜像1 小时前
Swift学习总结——使用Playground
前端·ios·面试
高冷的小明1 小时前
React-Find 一款能快速在网页定位到源码的工具,支持React19.x/next 15
前端·javascript·react.js