前端自适应方案
-
基于rem的适配方案
-
rem: 指相对于根元素的字体大小的单位,在日常开发过程中我们通常把根元素(html/body)的字体设置为10px,方便于我们计算(此时子元素的1rem就相当于10px)
-
适用场景: 不固定宽高比的Web应用,适用于绝大部分业务场景
-
使用方式
- 安装依赖
npm i postcss-pxtorem autoprefixer amfe-flexible --save-dev
注:postcss-pxtorem 是PostCSS的插件,用于将像素单元生成rem单位 autoprefixer 浏览器前缀处理插件 amfe-flexible 可伸缩布局方案 替代了原先的
lib-flexible
选用了当前众多浏览器兼容的viewport
- 项目根目录创建
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转换 }, }, };
main.ts/js
文件中导入依赖
import "amfe-flexible/index.js";
- 项目重启即可
- **建议:**vscode安装 px to rem & rpx & vw (cssrem)插件,同时在vscode左上角的文件 – 首选项 – 设置(左下角管理 – 设置) – 输入框输入“root”,找到 "基准font-size "更改为192,然后在就能够根据视觉稿中的像素值进行自动转化rem值。
-
-
基于scale的适配方案
-
在CSS3中,我们可以使用transform属性的scale()方法来实现元素的缩放效果。缩放,指的是“缩小”和“放大”的意思。
-
transform: scaleX(x); / 沿x轴方向缩放/
-
transform: scaleY(y); / 沿y轴方向缩放/
-
transform: scale(); / 同时沿x轴和y轴缩放/
-
适用场景:固定宽高比的Web应用,如大屏或者固定窗口业务应用
-
使用方式(Vue2)
- 新建
resize.ts/js
文件
// * 设计稿尺寸(px) export const w = 1920; export const h = 1080; export default { data() { return { screenRef: null, scale: 1, timer: null, delay: 200, }; }, methods: { resize() { // 浏览器宽高 const clientWidth = document.body.clientWidth; const clientHeight = document.body.clientHeight; // 计算宽高缩放比例 const scaleW = clientWidth / w; const scaleH = clientHeight / h; if (clientWidth / clientHeight > w / h) { // 如果浏览器的宽高比大于设计稿的宽高比,就取浏览器高度和设计稿高度之比 this.scale = scaleH; } else { // 如果浏览器的宽高比小于设计稿的宽高比,就取浏览器宽度和设计稿宽度之比 this.scale = scaleW; } this.screenRef.style.transform = "scale(" + this.scale + ")"; }, resizeDelay() { clearTimeout(this.timer); this.timer = window.setTimeout(() => { this.resize(); }, this.delay); }, setRef(ele, delay) { this.screenRef = ele; this.delay = delay; this.resize(); }, }, mounted() { window.addEventListener("resize", this.resizeDelay); }, beforeDestroy() { clearTimeout(this.timer); this.timer = null; window.removeEventListener("resize", this.resizeDelay); }, };
-
相关界面引入
resize.ts/js
<template> <div class="visualization"> <div class="es-screen" ref="screenRef"></div> </div> </template> <script> import windowResize from './minxins/resize'; export default { name: 'App', components: {}, mixins: [windowResize], data() { return {} }, mounted() { this.$nextTick(() => { this.setRef(this.$refs.screenRef, 200); }); }, } </script> <style lang="less" scoped> .visualization { --es-screen-width: 1920px; --es-screen-height: 1080px; --es-header-height: 72px; --es-block-bg: #222733; --es-screen-bg: rgb(22, 21, 34); --es-screen-text-color: #fff; position: relative; margin: 0; width: 100%; height: 100%; background-size: 100% 100%; overflow: hidden; background: var(--es-screen-bg); color: var(--es-screen-text-color); .es-screen { position: absolute; user-select: none; top: 50%; left: 50%; width: var(--es-screen-width); height: var(--es-screen-height); margin-left: calc(var(--es-screen-width) * 0.5 - var(--es-screen-width)); margin-top: calc(var(--es-screen-height) * 0.5 - var(--es-screen-height)); background-size: 100% 100%; padding: 0 20px; background-color: pink; } } </style>
- 新建
-
注意:如果是通过mixins的方法引入,需要在main.js文件加入下面代码:
import minxins from './minxins/resize'; Vue.use(minxins);
-
使用方式(Vue3)
-
新建
resize.ts/js
文件import { ref, onMounted, onBeforeUnmount } from 'vue' // 默认适配宽高 export const width = 1920 export const height = 1080 type ResizeType = { w?: number h?: number fullScreen?: boolean delay?: number } export const useResize = (options: ResizeType = {}) => { const { w = width, h = height, fullScreen = false, delay = 100 } = options // 缩放元素 const screenRef = ref() const scale = ref(1) function resize() { // 浏览器宽高 const clientWidth = document.body.clientWidth const clientHeight = document.body.clientHeight // 计算宽高缩放比例 const scaleW = clientWidth / w const scaleH = clientHeight / h if (clientWidth / clientHeight > w / h) { // 如果浏览器的宽高比大于设计稿的宽高比,就取浏览器高度和设计稿高度之比 scale.value = scaleH } else { // 如果浏览器的宽高比小于设计稿的宽高比,就取浏览器宽度和设计稿宽度之比 scale.value = scaleW } if (fullScreen) { // 如果不在乎缩放失真的情况,可以设置全屏 screenRef.value.style.transform = `scale(${scaleW}, ${scaleH})` } else { // 否则选择适配比例缩放 screenRef.value.style.transform = 'scale(' + scale.value + ')' } } const resizeDelay = debounce(resize, delay) onMounted(() => { if (screenRef.value) { resize() window.addEventListener('resize', resizeDelay) } }) onBeforeUnmount(() => { window.removeEventListener('resize', resizeDelay) }) return { scale, screenRef } } /* 用来返回防抖函数的工具函数 */ function debounce(callback, delay) { let timerId return function (event) { // 如果上次事件还没有真正处理, 清除 if (timerId) { clearTimeout(timerId) } // 发事件发生指定事件后才调用处理事件的回调函数 // 启动定时器, 只是准备真正处理 timerId = setTimeout(() => { // 正在处理事件 callback.call(null, event) // 删除准备处理的标记 timerId = null }, delay) } }
-
相关界面引入
resize.ts/js
<template> <div class="screen-container"> <div class="screen-content" ref="screenRef"></div> </div> </template> <script setup lang='ts'> import { useResize } from '@/utils/useResize' const { screenRef } = useResize() </script> <style lang='scss' scoped> .es-screen-container { --es-screen-width: 1920px; --es-screen-height: 1080px; --es-header-height: 72px; --es-block-bg: #222733; --es-screen-bg: rgb(22, 21, 34); --es-screen-text-color: #fff; position: relative; margin: 0; width: 100%; height: 100%; background-size: 100% 100%; overflow: hidden; background: var(--es-screen-bg); color: var(--es-screen-text-color); } .es-screen { position: absolute; user-select: none; top: 50%; left: 50%; width: var(--es-screen-width); height: var(--es-screen-height); margin-left: calc(var(--es-screen-width) * 0.5 - var(--es-screen-width)); margin-top: calc(var(--es-screen-height) * 0.5 - var(--es-screen-height)); background-size: 100% 100%; padding: 0 20px; } </style>
-
-