在做可视化大屏项目的时候,适配不同分辨率屏幕的电脑是最头疼的问题,那么,有没有一种方案,可以解决大屏适配问题呢。
在不懈的努力查找以及总结后,得到了一套,个人认为比较科学的适配方案。
线上demo例子
设计图宽高比例固定,并且跟随页面变化,等比例缩放
前端只需要按照设计图(px)单位设计开发即可,效果如图:
无论窗口缩放,屏幕放大缩小,我们的可视化界面都可以按照设计图比例正常展示,不会出现字体模块爆出,或者拉伸问题。这就是我想要的适配方案。
给最外层的盒子(body也行)加上标识(id, 或ref)
xxx(反正就是整个可视化页面内容)
这里仅展示id标识符的css样式
#appRef {
width: 1920px; /* 设计图宽 */
height: 1080px; /* 设计图高 */
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
transform-origin: left top;
overflow: hidden;
}
为了方便copy一点,这里就把普通html开发的适配js写法直接奉上
// * 默认缩放值
const scale = {
width: '1',
height: '1',
}
// * 设计稿尺寸(px)
const baseWidth = 1920
const baseHeight = 1080
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
let drawTiming = null
calcRate()
window.addEventListener('resize', resize)
// * 初始化页面比例
function calcRate () {
const appRef = document.getElementById("appRef")
if (!appRef) return
// 当前宽高比
const currentRate = parseFloat((window.innerWidth / window.innerHeight).toFixed(5))
if (appRef) {
if (currentRate > baseProportion) {
// 表示更宽
scale.width = ((window.innerHeight * baseProportion) / baseWidth).toFixed(5)
scale.height = (window.innerHeight / baseHeight).toFixed(5)
appRef.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)`
} else {
// 表示更高
scale.height = ((window.innerWidth / baseProportion) / baseHeight).toFixed(5)
scale.width = (window.innerWidth / baseWidth).toFixed(5)
appRef.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)`
}
}
}
// * 窗口大小变化
function resize () {
clearTimeout(drawTiming)
// 加延迟是为了更好的看到变化的过程,不需要的可以不用
drawTiming = setTimeout(() => {
calcRate()
}, 200)
}
vue开发的同理,为了方便copy,代码直接奉上
// * 默认缩放值
const scale = {
width: '1',
height: '1',
}
// * 设计稿尺寸(px)
const baseWidth = 1920
const baseHeight = 1080
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
export default {
data() {
return {
drawTiming: null // 定时函数
}
},
mounted () {
this.calcRate()
window.addEventListener('resize', this.resize)
},
methods: {
// 初始化页面比例
calcRate () {
const appRef = this.$refs["appRef"]
if (!appRef) return
// 当前宽高比
const currentRate = parseFloat((window.innerWidth / window.innerHeight).toFixed(5))
if (appRef) {
if (currentRate > baseProportion) {
// 表示更宽
scale.width = ((window.innerHeight * baseProportion) / baseWidth).toFixed(5)
scale.height = (window.innerHeight / baseHeight).toFixed(5)
appRef.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)`
} else {
// 表示更高
scale.height = ((window.innerWidth / baseProportion) / baseHeight).toFixed(5)
scale.width = (window.innerWidth / baseWidth).toFixed(5)
appRef.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)`
}
}
},
// 窗口大小变化
resize () {
clearTimeout(this.drawTiming)
this.drawTiming = setTimeout(() => {
this.calcRate()
}, 200)
}
},
beforeDestroy () {
window.removeEventListener('resize', this.resize)
},
}
在所有script的最后面引入就行,如图:
使用mixin混入引入(或者其他方式也行,个人习惯)
xxx
自适应全屏,不管屏幕宽高比如何,都以铺满全屏的形式进行展示。(适用于页面布局为百分比、或者flex自适应布局)
const appRef = document.getElementById("appRef")
// 初始化页面
calcRate()
window.addEventListener('resize', calcRate)
function calcRate () {
if (!appRef) return
// 获取浏览器缩放比例
const browserRoom = getZoom()
/**
* 1. 先将宽高乘上浏览器缩放倍数x
* 2. 再将整个页面用scale缩放 1/x 倍
* 在视觉上,就感觉页面没有缩放
*/
// 宽高
const w = window.innerWidth * browserRoom
const h = window.innerHeight * browserRoom
// scale缩放比例
const scl = parseFloat((1 / browserRoom).toFixed(5))
// 页面重绘处理
appRef.style.width = `${w}px`
appRef.style.height = `${h}px`
appRef.style.transform = `scale(${scl}, ${scl}) translate(-50%, -50%)`
// 页面重绘完成后,再进行echarts重绘,保证echarts图表的自适应性
myChart.resize()
myChart2.resize()
}
// 获取浏览器缩放比例
function getZoom() {
let ratio = 0,
screen = window.screen,
ua = navigator.userAgent.toLowerCase();
if (window.devicePixelRatio !== undefined) {
ratio = window.devicePixelRatio;
} else if (~ua.indexOf('msie')) {
if (screen.deviceXDPI && screen.logicalXDPI) {
ratio = screen.deviceXDPI / screen.logicalXDPI;
}
} else if (window.outerWidth !== undefined && window.innerWidth !== undefined) {
ratio = window.outerWidth / window.innerWidth;
}
if (ratio){
ratio = Math.round(ratio * 100);
}
return parseFloat(ratio/100).toFixed(2);
}
总结:只要是按照设计图,正常开发的大屏项目,此方案基本都能很好的完成适配,切记别在项目中用rem单位就行,这玩意儿不行,拜拜~