Vue3基于 rem 比例缩放方案示例详解

 更新时间:2023年05月30日 09:10:01   作者:懮 俍  
这篇文章主要介绍了Vue3基于rem比例缩放方案,本缩放方案置于hooks中即可,文中通过示例代码介绍了vue-cli3 中使用rem布局的方法,需要的朋友可以参考下

Vue3基于 rem 比例缩放方案

本缩放方案置于hooks中即可。于App.vue中引入并调用。会在页面DOM结构最外层增加响应式的font-size属性样式更改。

主要包含了以下内容

1.接口和类型定义:

  • DesignParms:设计稿参数的接口定义,包括宽度、高度和字体大小等信息。
  • UseRemOption:使用 rem 的配置参数的接口定义,包括延迟触发时间。
  • Designs:设计稿集合的类型定义,是一个由 DesignParms 构成的数组。

2.默认设计稿方案和配置参数:

  • DEFAULT_DESIGNS:默认的设计稿方案,包含多个不同分辨率下的设计稿信息。
  • DEFAULT_OPTION:默认的配置参数,包括延迟触发时间。

3.useEqualScaling 函数:

  • 该函数接受设计稿集合和配置参数作为参数,并返回缩放信息和方法。
  • 函数内部根据窗口大小和设计稿信息计算最合适的设计稿作为参考设计稿。
  • 在页面加载和窗口大小改变时,会触发 setHtmlFontSize 方法进行根节点字体大小的计算和设置。
  • 函数返回设计稿集合、参考设计稿和设置根节点字体大小的方法
/**
 * 基于rem 的比例缩放方案
 * @author wangguanjie 2022.06.09
 */
import { onBeforeUnmount, onMounted, ref } from "vue";
/**
 * 设计稿参数
 * @example 1920 * 1080 下 {width: 1920, height: 1080, fontSize: 16, ...}
 * @example 1680 * 1050 下 {width: 1680, height: 1050, fontSize: 14, ...}
 * @example 1280 * 800 下 {width: 1280, height: 800, fontSize: 12, ...}
 */
export interface DesignParms {
  width: number;
  height: number;
  fontSize: number;
}
export interface UseRemOption {
  delay?: number;
}
export type Designs = DesignParms[];
/**
 * 默认设计稿方案
 */
const DEFAULT_DESIGNS: Designs = [
  { width: 800, height: 600, fontSize: 12 },
  { width: 1024, height: 500, fontSize: 12 },
  { width: 1024, height: 768, fontSize: 12 }, // HD
  { width: 1280, height: 800, fontSize: 12 }, // WXGA
  { width: 1280, height: 854, fontSize: 12 },
  { width: 1280, height: 1024, fontSize: 12 },
  { width: 1366, height: 768, fontSize: 14 },
  { width: 1440, height: 900, fontSize: 14 },
  { width: 1440, height: 1050, fontSize: 14 },
  { width: 1600, height: 1024, fontSize: 14 },
  { width: 1600, height: 1200, fontSize: 14 }, // UXGA
  { width: 1680, height: 1050, fontSize: 14 },
  { width: 1920, height: 937, fontSize: 16 }, // FHD
  { width: 1920, height: 1080, fontSize: 16 }, // FHD
  { width: 1920, height: 1200, fontSize: 16 }, // WUXGA
  { width: 2048, height: 1080, fontSize: 18 },
  { width: 2048, height: 1536, fontSize: 18 }, // QXGA
  { width: 2560, height: 1080, fontSize: 18 },
  { width: 2560, height: 1440, fontSize: 18 }, // QHD
  { width: 2560, height: 1600, fontSize: 18 }, // WQXGA
  { width: 3440, height: 1440, fontSize: 18 },
  { width: 3840, height: 1080, fontSize: 18 },
  { width: 3840, height: 2160, fontSize: 18 }, // UHD
  { width: 4096, height: 2160, fontSize: 18 }, // 4K Ultra HD
];
/**
 * 默认配置参数
 */
const DEFAULT_OPTION: Required<UseRemOption> = {
  // 触发延时,默认2022
  delay: 0,
};
/**
 * 等比缩放方案
 * @author wangguanjie 2022.06.09
 * @description 该方案支持多设计稿
 * @param designs 设计稿集合
 * @param option 缩放配置参数
 * @returns 缩放信息、方法
 */
export const useEqualScaling = function (
  designs: Designs = DEFAULT_DESIGNS,
  option: UseRemOption = DEFAULT_OPTION
) {
  let timer: number | undefined;
  // 确保有设计稿可参考
  designs = designs.length ? designs : DEFAULT_DESIGNS;
  // 将设计搞进行升序排序,供后续快速排查
  designs
    .filter((d) => d.width > 1 && d.height > 1)
    .sort((d1, d2) => {
      if (d1.width === d2.width) {
        return d1.height - d2.height;
      }
      return d1.width - d2.width;
    });
  // 降序排序的设计稿
  const descendingDesigns = designs.map((d) => d).reverse();
  // 浏览器适配所参考的设计稿
  const referDesign = ref(designs[0]);
  /**
   * 根据多份设计搞自适应根节点字号
   */
  const setHtmlFontSize = () => {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      const { clientWidth: docW, clientHeight: docH } =
        document.documentElement;
      // 匹配最佳设计稿
      const hasNewReferDesignIndex = designs.findIndex(
        (d) => d.width >= docW && d.height >= docH
      );
      if (hasNewReferDesignIndex !== -1) {
        referDesign.value = designs[hasNewReferDesignIndex];
      } else {
        // 优先筛选宽度符合的设计搞
        const accordWidthDesigns = descendingDesigns.filter(
          (d) => d.width <= docW
        );
        // 再确认最接近设计稿高度的设计稿
        const designsHeightList = accordWidthDesigns.map((d) => d.height);
        const useDesignIndex = designsHeightList
          .map((designH) => Math.abs(docH - designH))
          .findIndex(
            (designH) =>
              designH ===
              Math.min(...designsHeightList.map((dh) => Math.abs(docH - dh)))
          );
        referDesign.value = accordWidthDesigns[useDesignIndex];
      }
      // 依据所参考的设计稿变更根节点字号
      const documentRatio = docW / docH;
      const {
        width: designW,
        height: designH,
        fontSize: designFontSize,
      } = referDesign.value;
      const designRatio = designW / designH;
      const htmlFontSize =
        documentRatio < designRatio
          ? (docW / designW) * designFontSize
          : (docH / designH) * designFontSize;
      const html = document.querySelector("html");
      if (html) {
        html.style.fontSize = `${htmlFontSize}px`;
      }
    }, option.delay ?? DEFAULT_OPTION.delay);
  };
  setHtmlFontSize();
  onMounted(() => {
    window.addEventListener("resize", setHtmlFontSize, false);
  });
  onBeforeUnmount(() => {
    window.removeEventListener("resize", setHtmlFontSize, false);
  });
  return {
    designs,
    referDesign,
    setHtmlFontSize,
  };
};

vue-cli3 中使用rem布局

1. 装包postcss-px2rem及px2rem-loader

npm install postcss-px2rem px2rem-loader --save

2. 在根目录src中新建utils目录下新建rem.js等比适配文件,内容如下

// rem等比适配配置文件
// 基准大小
const baseSize = 16
// 设置 rem 函数
function setRem () {
  // 当前页面宽度相对于 1920宽的缩放比例,可根据自己需要修改。
  const scale = document.documentElement.clientWidth / 1920
  // 设置页面根节点字体大小(“Math.min(scale, 2)” 指最高放大比例为2,可根据实际业务需求调整)
  document.documentElement.style.fontSize = baseSize * Math.min(scale, 2) + 'px'
}
// 初始化
setRem()
// 改变窗口大小时重新设置 rem
window.onresize = function () {
  setRem()
}

3.在main.js中引入适配文件

import './utils/rem'

4.到vue.config.js中配置插件

// 引入等比适配插件
const px2rem = require('postcss-px2rem')
// 配置基本大小
const postcss = px2rem({
  // 基准大小 baseSize,需要和rem.js中相同
  remUnit: 16
})
// 使用等比适配插件
module.exports = {
  lintOnSave: true,
  css: {
    loaderOptions: {
      postcss: {
        plugins: [
          postcss
        ]
      }
    }
  }
}

到此这篇关于Vue3基于 rem 比例缩放方案的文章就介绍到这了,更多相关Vue3比例缩放内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue项目中怎样嵌入其它项目的页面

    vue项目中怎样嵌入其它项目的页面

    这篇文章主要介绍了vue项目中怎样嵌入其它项目的页面问题,具有很好 的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • 详解Vue单元测试Karma+Mocha学习笔记

    详解Vue单元测试Karma+Mocha学习笔记

    本篇文章主要介绍了详解Vue单元测试Karma+Mocha学习笔记,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • Vue+Vuex实现自动登录的知识点详解

    Vue+Vuex实现自动登录的知识点详解

    在本篇文章里小编给大家整理的是关于Vue+Vuex实现自动登录的知识点详解,需要的朋友们可以学习下。
    2020-03-03
  • 一定要知道的 25 个 Vue 技巧

    一定要知道的 25 个 Vue 技巧

    这篇文章主要给大家分享将 prop 限制为类型列表、默认内容和扩展点、使用引号观察嵌套值、知道何时使用 v-if、单作用域 slot 的简写、有条件地渲染slot等25 个Vue 技巧,下文是下相关资料,需要的朋友可以参考一下
    2021-11-11
  • vue history 模式打包部署在域名的二级目录的配置指南

    vue history 模式打包部署在域名的二级目录的配置指南

    这篇文章主要介绍了vue history 模式打包部署在域名的二级目录的配置指南 ,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-07-07
  • vue3父组件和子组件如何传值实例详解

    vue3父组件和子组件如何传值实例详解

    近期学习vue3的父子组件之间的传值,发现跟vue2.x的父子组件之间的传值并没有太大的区别,下面这篇文章主要给大家介绍了关于vue3父组件和子组件如何传值的相关资料,需要的朋友可以参考下
    2022-08-08
  • TypeError:res.forEach is not a function报错解决办法

    TypeError:res.forEach is not a function报错解决办法

    这篇文章主要给大家介绍了关于TypeError:res.forEach is not a function报错的解决办法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2023-07-07
  • Vue Element-ui表单校验规则实现

    Vue Element-ui表单校验规则实现

    Element-ui表单校验规则,使得错误提示可以直接在form-item下面显示,无需弹出框,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • Vue实现自定义字段导出EXCEL的示例代码

    Vue实现自定义字段导出EXCEL的示例代码

    这篇文章主要介绍了Vue实现自定义字段导出EXCEL的示例代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • vue实现选项卡及选项卡切换效果

    vue实现选项卡及选项卡切换效果

    这篇文章主要介绍了vue实现选项卡选项卡切换效果,这里的Vue以单文件的形式引入,另外代码在实现上会一步步的进行优化。需要的朋友可以参考下
    2018-04-04

最新评论