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总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
