前端大屏项目等比例适配方案
最近正在完成一个大屏项目,按照设计图的尺寸,使用固定px完成了页面的整体设计,但是由于现实等多方面因素,需要放在不同的大屏上进行展示,因此采用了transform方案进行整体缩放,但是遇到不在可视屏幕居中的问题,下面就是介绍解决方案
1. 借鉴方案
点击跳转=》方案链接
采用此方案可以实现对设计稿的缩放剧中显示,但是由于大屏中有 地图模块,此方案中transform-origin: left top; 改变了地图的缩放中心,使之处于左上角,并不是在地图模块的中心进行缩放,所以此方案并不适用于我,于是我进行了改进
1.1 实现原理
- html模块
// html结构
<div id="index" ref="appRef">
</div>
//css
#index {
color: #d3d6dd;
//此处的宽高就是你设计稿的尺寸
width: 1920px;
height: 1080px;
//绝对定位 脱离标准流
position: absolute;
//分别将 div容器向左 和 向下 移动50%
top: 50%;
left: 50%;
// 设置以容器左上角为中心,进行缩放移动
transform-origin: left top;
//再将容易往反方向分别移动50%,这样div容器 一直处于可视窗口中心
transform: translate(-50%, -50%);
//超出部位隐藏
overflow: hidden;
}
- 缩放函数
// 屏幕适配 mixin 函数
// * 默认缩放值
const scale = {
width: '1',
height: '1',
}
// * 设计稿尺寸(px)
const baseWidth = 1920
const baseHeight = 1080
// * 需保持的比例(默认1.77778)
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
export default {
data() {
return {
// * 定时函数
drawTiming: null
}
},
mounted () {
//进入触发
this.calcRate()
window.addEventListener('resize', this.resize)
},
beforeDestroy () {
window.removeEventListener('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)
console.log(scale.width,scale.height,'放大');
//整个页面的元素样式,缩放宽高用当前同比例放大的宽高
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)
console.log(scale.width,scale.height,'缩小');
//整个页面的元素样式,缩放宽高用当前同比例放大的宽高
appRef.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)`
}
}
},
resize () {
clearTimeout(this.drawTiming)
this.drawTiming = setTimeout(() => {
this.calcRate()
}, 200)
}
},
}
2. 改进方案
-
此方案采用计算方式,使div容器在可视窗口内剧中显示,并且并不影响视图操作中心
-
html模块
// html结构
<div id="index" ref="appRef">
</div>
//css
#index {
text-align: left;
color: #4449a3;
//设计稿大小
height: 2270px;
width: 6720px;
padding: 0;
//将容器设置为 绝对定位,脱离标准流
position: absolute;
overflow: hidden;
}
- 缩放函数
// 屏幕适配 mixin 函数
// * 默认缩放值
const scale = {
width: '1',
height: '1',
}
// * 设计稿尺寸(px)
const baseWidth = 1920
const baseHeight = 1080
// * 需保持的比例(默认1.77778)
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
export default {
data() {
return {
// * 定时函数
drawTiming: null
}
},
mounted () {
//进入触发
this.calcRate()
window.addEventListener('resize', this.resize)
},
beforeDestroy () {
window.removeEventListener('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)
console.log(scale.width, scale.height, '放大');
//整个页面的元素样式,缩放宽高用当前同比例放大的宽高
appRef.style.transform = `scale(${scale.width}, ${scale.height})`
} else {
// 如果不大于默认比例代表缩小了。
//那么把默认缩放的宽高改为:同比例缩小
scale.height = ((window.innerWidth / baseProportion) / baseHeight).toFixed(5)
scale.width = (window.innerWidth / baseWidth).toFixed(5)
console.log(scale.width, scale.height, '缩小');
//整个页面的元素样式,缩放宽高用当前同比例放大的宽高
appRef.style.transform = `scale(${scale.width}, ${scale.height})`
}
//等dom节点加载完后执行
this.$nextTick(() => {
//appRef.getBoundingClientRect() 为获取当前div容器距离windows视图的上边距与左边距
let appRefBoundingClientRect = appRef.getBoundingClientRect()
// 第一种方式
// let finallyTop = this.prevAppRefBoundingClientRect.top === 0 ? -appRefBoundingClientRect.top : (this.prevAppRefBoundingClientRect.top - appRefBoundingClientRect.top)
// let finallyLeft = this.prevAppRefBoundingClientRect.left === 0 ? -appRefBoundingClientRect.left : (this.prevAppRefBoundingClientRect.left - appRefBoundingClientRect.left)
// appRef.style.top = `${finallyTop}px`
// appRef.style.left = `${finallyLeft}px`
// this.prevAppRefBoundingClientRect.top = finallyTop
// this.prevAppRefBoundingClientRect.left = finallyLeft
// 第二种方式
let finallyTop = 0;
let finallyLeft = 0;
if (this.isFirst) {
// 第一次缩放偏移量
finallyTop = appRefBoundingClientRect.top
finallyLeft = appRefBoundingClientRect.left
this.isFirst = false;
} else {
// 第二次变化后的缩放偏移量
finallyTop = this.prevAppRefBoundingClientRect.top * (1 - scale.height) / (1 - this.scalePrev)
finallyLeft = this.prevAppRefBoundingClientRect.left * (1 - scale.height) / (1 - this.scalePrev)
}
// 设置缩放元素偏移量
appRef.style.top = `${-finallyTop}px`;
appRef.style.left = `${-finallyLeft}px`;
this.scalePrev = scale.width;
this.prevAppRefBoundingClientRect.top = finallyTop
this.prevAppRefBoundingClientRect.left = finallyLeft
});
}
},
resize () {
clearTimeout(this.drawTiming)
this.drawTiming = setTimeout(() => {
this.calcRate()
}, 200)
}
},
}