总结一下我常用的数据大屏自适应方法
目录
1、通过css缩放方案: 利用transform:scale 进行适配
我一般使用 v-scale-screen 插件
主要用于同比例缩放,例如16:9(1k,2k,4k)
vue2版本(npm官网):https://www.npmjs.com/package/vue2-scale-box
vue3版本(npm官网):https://www.npmjs.com/package/vue3-scale-box
yarn add vue3-scale-box
<template>
<ScaleBox
:width="1920"
:height="1080"
bgc="transparent"
:delay="100"
:isFlat="false"
>
<div class="ec-demo" id="ec-demo"></div>
</ScaleBox>
</template>
<script setup>
import ScaleBox from "vue3-scale-box";
</script>
2、采用rem布局, 根据屏幕分辨率大小不同,调整根元素html的font-size, 从而达到每个元素宽高自动变化,适配不同屏幕
我一般使用 postcss-pxtorem + lib-flexible 插件
主要用于多个不同比例缩放,例如16:9(1k,2k,4k),21:9或其他比例
适配的方法总体分为两步:
- px转换成rem
- rem根据屏幕大小重置基数改变大小
2.1、先下载postcss-pxtorem
yarn add postcss-pxtorem
"postcss-pxtorem": "^6.0.0",
2.2、在vite.config.ts配置
import postcssPxtoRem from "postcss-pxtorem";
css: {
postcss: {
plugins: [
postcssPxtoRem({
rootValue: 192, // 按照自己的设计稿修改 1920/10
unitPrecision: 5, // 保留到5位小数
selectorBlackList: ["ignore"], // 忽略转换正则匹配项
propList: ["*", "!border"],
replace: true,
mediaQuery: false, // 媒体查询( @media screen 之类的)中不生效
minPixelValue: 1, //可以选择px小于1的不会被转换
}),
],
},
},
2.3、在src/utils下创建flexible.js文件(lib-flexible插件建议放到本地)
因为我要适配不同比例的大屏,我把lib-flexible插件放在了本地(方便修改)
可以在 refreshRem() 方法中对不同分辨率进行设置
(function (win, lib) {
var doc = win.document;
var docEl = doc.documentElement;
var metaEl = doc.querySelector('meta[name="viewport"]');
var flexibleEl = doc.querySelector('meta[name="flexible"]');
var dpr = 0;
var scale = 0;
var tid;
var flexible = lib.flexible || (lib.flexible = {});
if (metaEl) {
console.warn("将根据已有的meta标签来设置缩放比例");
var match = metaEl
.getAttribute("content")
.match(/initial\-scale=([\d\.]+)/);
if (match) {
scale = parseFloat(match[1]);
dpr = parseInt(1 / scale);
}
} else if (flexibleEl) {
var content = flexibleEl.getAttribute("content");
if (content) {
var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
if (initialDpr) {
dpr = parseFloat(initialDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2));
}
if (maximumDpr) {
dpr = parseFloat(maximumDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2));
}
}
}
if (!dpr && !scale) {
var isAndroid = win.navigator.appVersion.match(/android/gi);
var isIPhone = win.navigator.appVersion.match(/iphone/gi);
var devicePixelRatio = win.devicePixelRatio;
if (isIPhone || isAndroid) {
// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
dpr = 3;
} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)) {
dpr = 2;
} else {
dpr = 1;
}
} else {
// 其他设备下,仍旧使用1倍的方案
dpr = devicePixelRatio;
}
scale = 1 / dpr;
// scale = 1 * dpr;
}
docEl.setAttribute("data-dpr", dpr);
if (!metaEl) {
metaEl = doc.createElement("meta");
metaEl.setAttribute("name", "viewport");
metaEl.setAttribute(
"content",
"initial-scale=" +
scale +
", maximum-scale=" +
scale +
", minimum-scale=" +
scale +
", user-scalable=no"
);
if (docEl.firstElementChild) {
docEl.firstElementChild.appendChild(metaEl);
} else {
var wrap = doc.createElement("div");
wrap.appendChild(metaEl);
doc.write(wrap.innerHTML);
}
}
function refreshRem() {
var width = docEl.getBoundingClientRect().width;
var height = docEl.getBoundingClientRect().height;
if (width / dpr < 1600) {
width = 1920 * dpr;
}
var rem = (width * dpr) / 10;
docEl.style.fontSize = rem + "px";
flexible.rem = win.rem = rem;
// if(width>3040&&width<3640){
// docEl.style.fontSize = 1 + "px";
// flexible.rem = 1 + "px";
// }
}
win.addEventListener(
"resize",
function () {
refreshRem();
},
false
);
win.addEventListener(
"pageshow",
function (e) {
if (e.persisted) {
refreshRem();
}
},
false
);
if (doc.readyState === "complete") {
doc.body.style.fontSize = 12 * dpr + "px";
} else {
doc.addEventListener(
"DOMContentLoaded",
function () {
doc.body.style.fontSize = 12 * dpr + "px";
},
false
);
}
refreshRem();
flexible.dpr = win.dpr = dpr;
flexible.refreshRem = refreshRem;
flexible.rem2px = function (d) {
var val = parseFloat(d) * this.rem;
if (typeof d === "string" && d.match(/rem$/)) {
val += "px";
}
return val;
};
flexible.px2rem = function (d) {
var val = parseFloat(d) / this.rem;
if (typeof d === "string" && d.match(/px$/)) {
val += "rem";
}
return val;
};
})(window, window["lib"] || (window["lib"] = {}));
2.4、在main.js中引入flexible.js
//px转rem
// 使用下面@ts-ignore表示忽略ts类型检测,否则下面代码打包时会报错
import '@/utils/flexible.js'
2.5、注意事项
1、 框架组件和标签中直接定义的 width和height进行不了转换, 例如img标签
2、 大多框架只适配1920*1080的,其他比例,框架组件可能会变形,需要单独设置,可以在全局css文件进行修改。