使用 scale 适配大屏。实现数据大屏在任何分辨率的电脑上均可安然运作。无需特定编写 rem 单位,也不需要考虑单位使用失误导致适配不完全。您即使全部用 position 去定位在其他屏幕上都不会乱。(%和 px 随便用)

布局

在 vue2 中的写法如下:

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
<template>
<div class="dataScreen-container">
<div class="dataScreen" ref="dataScreenRef">
<div class="dataScreen-header">
<div class="header-lf"></div>
<div class="header-ct"></div>
<div class="header-rg"></div>
</div>
<div class="dataScreen-main">
<div class="dataScreen-lf"></div>
<div class="dataScreen-ct"></div>
<div class="dataScreen-rg"></div>
</div>
</div>
</div>
</template>

<script>
export default {
data() {
return {};
},
components: {},
mounted() {
this.init();
window.addEventListener('resize', this.resize);
},
beforeDestroy() {
window.removeEventListener('resize', resize);
},
methods: {
// 根据浏览器大小推断缩放比例
getScale(width = 1920, height = 1080) {
let ww = window.innerWidth / width;
let wh = window.innerHeight / height;
return ww < wh ? ww : wh;
},
// 初始化
init() {
const dataScreenRef = this.$refs.dataScreenRef;
// 初始化时为外层盒子加上缩放属性,防止刷新界面时就已经缩放
if (dataScreenRef) {
dataScreenRef.style.transform = `scale(${this.getScale()}) translate(-50%, -50%)`;
dataScreenRef.style.width = `1920px`;
dataScreenRef.style.height = `1080px`;
}
},
// 监听浏览器 resize 事件
resize() {
const dataScreenRef = this.$refs.dataScreenRef;
if (dataScreenRef) {
dataScreenRef.style.transform = `scale(${this.getScale()}) translate(-50%, -50%)`;
}
},
},
};
</script>

<style lang="scss" scoped>
@import './index.scss';
</style>

在 vue3 中的写法如下:

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
<template>
<div class="dataScreen-container">
<div class="dataScreen" ref="dataScreenRef">
<div class="dataScreen-header">
<div class="header-lf"></div>
<div class="header-ct"></div>
<div class="header-rg"></div>
</div>
<div class="dataScreen-main">
<div class="dataScreen-lf"></div>
<div class="dataScreen-ct"></div>
<div class="dataScreen-rg"></div>
</div>
</div>
</div>
</template>

<script setup lang="ts">
import { ref, Ref, onMounted, onBeforeUnmount } from 'vue';

const dataScreenRef = ref<HTMLElement | null>(null);

onMounted(() => {
// 初始化时为外层盒子加上缩放属性,防止刷新界面时就已经缩放
if (dataScreenRef.value) {
dataScreenRef.value.style.transform = `scale(${getScale()}) translate(-50%, -50%)`;
dataScreenRef.value.style.width = `1920px`;
dataScreenRef.value.style.height = `1080px`;
}
// 初始化echarts
initCharts();
// 为浏览器绑定事件
window.addEventListener('resize', resize);
});

// 声明echarts实例
interface ChartProps {
[key: string]: ECharts | null;
}
const dataScreen: ChartProps = {
chart1: null,
chart2: null,
chart3: null,
chart4: null,
mapChart: null,
};

// 初始化 echarts
const initCharts = (): void => {};

// 根据浏览器大小推断缩放比例
const getScale = (width = 1920, height = 1080) => {
let ww = window.innerWidth / width;
let wh = window.innerHeight / height;
return ww < wh ? ww : wh;
};

// 监听浏览器 resize 事件
const resize = () => {
if (dataScreenRef.value) {
dataScreenRef.value.style.transform = `scale(${getScale()}) translate(-50%, -50%)`;
}
// 使用了 scale 的echarts其实不需要需要重新计算缩放比例
Object.values(dataScreen).forEach(chart => {
chart && chart.resize();
});
};

// 销毁时触发
onBeforeUnmount(() => {
window.removeEventListener('resize', resize);
clearInterval(timer!);
Object.values(dataScreen).forEach(val => val?.dispose());
});
</script>
<style lang="scss" scoped>
@import './index.scss';
</style>

样式

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
.dataScreen-container {
width: 100%;
height: 100%;
background: url('./images/bg.png') no-repeat;
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center;
background-size: 100% 100%;
background-size: cover;
.dataScreen {
position: fixed;
top: 50%;
left: 50%;
z-index: 999;
display: flex;
flex-direction: column;
overflow: hidden;
transition: all 0.3s;
transform-origin: left top;
.dataScreen-header {
display: flex;
width: 100%;
height: 38px;

// .header-lf {
// }
// .header-rg {
// }
// .header-ct {
// }
}
.dataScreen-main {
box-sizing: border-box;
display: flex;
flex: 1;
width: 100%;
padding: 12px 42px 20px;

// .dataScreen-lf {
// }
// .dataScreen-ct {
// }
// .dataScreen-rg {
// }
}
}
}