vue适配屏幕分辨率,以及屏幕的缩放方式
作者:weixin_54820790
这篇文章主要介绍了vue适配屏幕分辨率,以及屏幕的缩放方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
vue适配屏幕分辨率以及屏幕的缩放
utils新建一个文件devicePixelRatio.js
class DisplayAdapter { constructor(options = {}) { this.options = { designWidth: 1920, // 设计稿基准宽度 baseFontSize: 16, // 基础字体大小 maxScale: 2, // 最大缩放比例 useTransform: true, // 使用transform缩放 debounceTime: 100, // 防抖时间 ...options }; this.lastDPR = window.devicePixelRatio; this.init(); } // 系统检测(增强版) _getSystem () { const agent = navigator.userAgent.toLowerCase(); const isWindows = /windows/.test(agent); const isHighDPI = window.devicePixelRatio >= 1.25; return isWindows && isHighDPI; } // 防抖函数 _debounce (fn) { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), this.options.debounceTime); }; } // 动态REM计算 _setRem () { const clientWidth = document.documentElement.clientWidth; const scale = Math.min(clientWidth / this.options.designWidth, this.options.maxScale); document.documentElement.style.fontSize = `${this.options.baseFontSize * scale}px`; } // DPI缩放校正 _correctDPR () { const currentDPR = window.devicePixelRatio; if (Math.abs(currentDPR - this.lastDPR) > 0.05) { this.lastDPR = currentDPR; if (this.options.useTransform) { const scale = 1 / currentDPR; document.body.style.transform = `scale(${scale})`; document.body.style.transformOrigin = 'top left'; document.body.style.width = `${this.options.designWidth / scale}px`; } else { document.body.style.zoom = 1 / currentDPR; } } } // 组合适配方法 _adaptLayout () { this._correctDPR(); this._setRem(); } // 事件监听 _watch () { const debouncedAdapt = this._debounce(() => this._adaptLayout()); const events = ['resize', 'pageshow', 'orientationchange']; events.forEach(event => { window.addEventListener(event, debouncedAdapt); }); // 监听DPI变化(仅现代浏览器) if (window.matchMedia) { window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`) .addEventListener('change', debouncedAdapt); } } // 初始化样式 _injectBaseStyles () { const style = document.createElement('style'); style.textContent = ` html { overflow: hidden; width: 100vw; height: 100vh; } body { position: relative; margin: 0; padding: 0; overflow: hidden; transform-origin: top left; } `; document.head.appendChild(style); } // 初始化 init () { if (this._getSystem()) { this._injectBaseStyles(); this._adaptLayout(); this._watch(); } else { // 非Windows系统仅启用REM适配 this._setRem(); window.addEventListener('resize', this._debounce(() => this._setRem())); } } } // 初始化配置 new DisplayAdapter({ designWidth: 1920, useTransform: true, maxScale: 1.5 }); export default DisplayAdapter;
在app.vue里面使用
import DevicePixelRatio from "@/utils/devicePixelRatio" created () { new DevicePixelRatio().init() }
utils里面再新建一个rem.js
// rem等比适配配置文件 // 基准大小 const baseSize = 16; // 设置 rem 函数 function setRem () { // 当前页面宽度相对于 1920宽的缩放比例,可根据自己需要修改。 const scale = document.documentElement.clientWidth / 1920; // 设置页面根节点字体大小(“Math.min(scale, 2)” 指最高放大比例为2,可根据实际业务需求调整) if (document.documentElement.clientWidth >= 2560) { document.documentElement.style.fontSize = baseSize * Math.min(scale, 2) + "px"; } else { document.documentElement.style.fontSize = baseSize * Math.min(scale, 1) + "px"; } } // 初始化 setRem(); // 改变窗口大小时重新设置 rem // window.onresize = function () { // setRem(); // }; window.addEventListener('resize', function () { setRem(); });
main.js中引用
import rem from "@/utils/rem";
vue.config.js里面修改
// 引入等比适配插件 const px2rem = require('postcss-px2rem'); // 配置基本大小 const postcss = px2rem({ // 基准大小 baseSize,需要和rem.js中相同 remUnit: 16, }); // 配置基本大小 const postcss = px2rem({ // 基准大小 baseSize,需要和rem.js中相同 // remUnit: 14 代表 1rem = 14px; 所以当你一个14px值时,它会自动转成 (14px/14)rem remUnit: 14 }) // 使用等比适配插件 module.exports = { lintOnSave: true, css: { loaderOptions: { scss: { additionalData: `@import "./src/assets/styles/module.scss";`, sassOptions: { outputStyle: "expanded" }, }, postcss: { plugins: [ postcss, ], }, }, }, }
与vue.config.js同根目录下创建postcss.config.js
// module.exports = { // plugins: { // 'postcss-px-to-viewport': { // // 设计稿宽度是电脑屏幕宽度 // unitToConvert: 'px', // 需要转换的单位,默认为"px" // viewportWidth: 1920, // 设计稿的视口宽度 // unitPrecision: 5, // 单位转换后保留的精度 // propList: ['*'], // 能转化为vw的属性列表 // viewportUnit: 'vw', // 希望使用的视口单位 // fontViewportUnit: 'vw', // 字体使用的视口单位 // selectorBlackList: [], // 需要忽略的CSS选择器 // minPixelValue: 1, // 最小的转换数值,如果为1的话,只有大于1的值会被转换 // mediaQuery: false, // 媒体查询里的单位是否需要转换单位 // replace: true, // 是否直接更换属性值,而不添加备用属性 // exclude: [], // 忽略某些文件夹下的文件或特定文件 // include: undefined, // 如果设置了include,那将只有匹配到的文件才会被转换,例如只转换 'src/mobile' 下的文件 (include: /\/src\/mobile\//) // landscape: false, // 是否添加根据 landscapeWidth 生成的媒体查询条件 @media (orientation: landscape) // landscapeUnit: 'vw' // 横屏时使用的单位 // }, // }, // }; // module.exports = () => ({ // plugins: [ // require("autoprefixer")(), // // require("postcss-px2rem")({ remUnit: 75 }) // require("postcss-pxtorem")({ // rootValue: 16,//结果为:设计稿元素尺寸/16,比如元素宽320px,最终页面会换算成 20rem // propList: ["*"] // }) // ] // }) //另一种可以新建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-px2rem": { rootValue: 16, //结果为:设计稿元素尺寸/16,比如元素宽320px,最终页面会换算成 20rem propList: ["*"], //是一个存储哪些将被转换的属性列表,这里设置为['*']全部,假设需要仅对边框进行设置,可以写['*', '!border*'] unitPrecision: 5, //保留rem小数点多少位 //selectorBlackList: ['.radius'], //则是一个对css选择器进行过滤的数组,比如你设置为['fs'],那例如fs-xl类名,里面有关px的样式将不被转换,这里也支持正则写法。 replace: true, //这个真不知到干嘛用的。有知道的告诉我一下 mediaQuery: false, //媒体查询( @media screen 之类的)中不生效 minPixelValue: 12, //px小于12的不会被转换 }, }, }; // 蓝湖上设计稿自定义为375px 测量值直接写入即可 若设计稿为750px 则rootValue: 32
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。