在做可视化大屏项目难免会考虑到屏幕适配的难题,如果有一个适配各种屏幕的基础容器组件处理这个事情,我们就可以放心写业务,下面介绍在vue中如何通过锁定宽高比的方式来进行屏幕适配。

组件特点

1.自动监听浏览器窗口变化,动态计算出高宽比,无视页面放大缩小

2.适用于各种屏幕,常用作项目最外层基础容器

3.突破浏览器中 font-size 最小 12px 限制

组件实现

新增LargeScreenContainer.vue文件,在文件里面创建一个外层包裹容器,根据屏幕的可视区尺寸与设计稿尺寸得到一个宽高缩放比例,根据比例去对外层包裹容器进行缩放,以适应屏幕

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<template>
<div>
<div id="well-container" :ref="refName">
<template v-if="ready">
<slot></slot>
</template>
</div>
</div>
</template>

<script>
import { debounce } from '@/utils/util.js'

export default {
name: 'largeScreenContainer',
props: {
options: Object
},
data() {
return {
refName: 'WellContainer',
width: 0, // 屏幕宽度
height: 0, // 屏幕高度
originalWidth: 0, // 原始屏幕宽度
originalHeight: 0, // 原始屏幕高度
ready: false, // 控制显示
dom: null, // well-container的dom
observer: null // window.MutationObserver(Bom实例)监听dom改变
}
},
methods: {
// 设置初始值
initSize() {
return new Promise((resolve) => {
this.$nextTick(() => {
this.dom = document.getElementById('well-container')
// 获取大屏的传入尺寸
if (this.options && this.options.width && this.options.height) {
// 传入宽高
this.width = this.options.width
this.height = this.options.height
} else {
// 可见宽高
this.width = this.dom.clientWidth
this.height = this.dom.clientHeight
}
// 获取画布尺寸
if (!this.originalWidth || !this.originalHeight) {
// 屏幕分辨率宽高
this.originalWidth = window.screen.width
this.originalHeight = window.screen.height
}
resolve()
})
})
},
updateSize() {
if (this.width && this.height) {
this.dom.style.width = `${this.width}px`
this.dom.style.height = `${this.height}px`
} else {
this.dom.style.width = `${this.originalWidth}px`
this.dom.style.height = `${this.originalHeight}px`
}
},
updateScale() {
// 获取真实的视口尺寸
const currentWidth = document.body.clientWidth
const currentHeight = document.body.clientHeight
// 获取大屏最终的宽高
const realWidth = this.width || this.originalWidth
const realHeight = this.height || this.originalHeight
console.log(currentWidth, currentHeight)
// 缩放比例 = 分辨率宽高 / 传入宽高(可视宽高)
const widthScale = currentWidth / realWidth
const heightScale = currentHeight / realHeight
// 如果dom存在,就按照比例缩放
this.dom && (this.dom.style.transform = `scale(${widthScale}, ${heightScale})`)
},
// 重置缩放比例
async onResize() {
await this.initSize()
this.updateScale()
this.$emit('resize')
},
initMutationObserver() {
// 监听元素属性变化
const MutationObserver = window.MutationObserver
// 如果变化,就用onResize重置屏幕所缩放比例
this.observer = new MutationObserver(this.onResize)
this.observer.observe(this.dom, {
attributes: true,
attributeFilter: ['style'],
attributeOldValue: true
})
},
// 移除监听属性
removeMutationObserver() {
if (this.observer) {
this.observer.disconnect()
this.observer.takeRecords()
this.observer = null
}
},
resize() {
debounce(this.onResize, 100)
}
},
async mounted() {
await this.initSize()
this.updateSize()
this.updateScale()
window.addEventListener('resize', this.resize)
this.initMutationObserver()
this.ready = true
},
beforeDestroy() {
window.removeEventListener('resize', this.resize)
this.removeMutationObserver()
}
}
</script>

<style lang="scss" scoped>

#well-container {
position: fixed;
top: 0;
left: 0;
overflow: hidden;
transform-origin: left top;
z-index: 999;
}
</style>

依赖文件 util.js,参考如下:

组件的使用

1
2
3
4
5
<large-screen-container
:options="{width:1920,height:1080}"
>
<!-- 子元素会根据缩放比例自动适配 -->
</large-screen-container>

核心原理

1
2
3
4
5
// 缩放比例  = 分辨率宽高 / 传入宽高(可视宽高)
const widthScale = currentWidth / realWidth
const heightScale = currentHeight / realHeight
// 如果dom存在,就按照比例缩放
this.dom && (this.dom.style.transform = `scale(${widthScale}, ${heightScale})`)

1.宽度度缩放比例(widthScale)= 分辨率宽高/props 传入宽高(可视宽高)

2.高度缩放比例(heightScale) = 分辨率高度/props 传入高度(可视高度)

3.通过 transform 的属性缩放容器的大