下面説下有兩種方式計算sacle,結果相同,只是方式不大同:
第一種:
一、在App.vue的props注入寬高
1 props: {
2 width: {
3 type: String,
4 default: "1920"
5 },
6 height: {
7 type: String,
8 default: "1080"
9 }
10 },
二、在data中定義style
1 style: {
2 width: this.width + "px",
3 height: this.height + "px",
4 transform: "scale(1) translate(-50%, -50%)"
5 }
三、在methods中定義方法
Debounce: (fn, t) => {
const delay = t || 500;
let timer;
return function() {
const args = arguments;
if (timer) {
clearTimeout(timer);
}
const context = this;
timer = setTimeout(() => {
timer = null;
fn.apply(context, args);
}, delay);
};
},
getScale() {
const w = window.innerWidth / this.width;
const h = window.innerHeight / this.height;
return w < h ? w : h;
},
setScale() {
this.style.transform =
"scale(" + this.getScale() + ") translate(-50%, -50%)";
}
四、給html標籤動態綁定 style
注意:如果寬高不夠等比,給最大的盒子一個背景色,下面的例子就是
<div id="app" style="background:linear-gradient(#112550, #0F2C74)">
<div class="ScreenAdapter" :style="style">
<router-view />
</div>
</div>
五、給類名 ScreenAdapter 添加css樣式
.ScreenAdapter {
transform-origin: 0 0;
position: absolute;
left: 50%;
top: 50%;
transition: 0.3s;
}
六、在 mounted 中調用 setScale()方法、和使用window.onresize 方法
this.setScale();
window.onresize = this.Debounce(this.setScale, 1000);
第二種:
背景:數據大屏項目,需要適配不同屏幕,且在任意屏幕下保持16:9的比例,保持顯示效果一致,屏幕比例不一致兩邊留黑即可
分析:
不同屏幕寬高比例(和設計稿16:9)相比會有兩種情況:
1、更寬:(window.innerWidth / window.innerHeight) > 16/9 ,以高度為基準,去適配寬度
2、更高:(window.innerWidth / window.innerHeight) < 16/9 ,以寬度為基準,去適配高度
選擇方案:
計算需要縮放的比例,利用transform的scale屬性縮放即可
為什麼不用px->rem或媒體查詢?
因為用rem起來太麻煩了;媒體查詢代碼大量書寫 比較繁瑣;而且echarts裏面的東西不好適配
使用transform可以完全按照設計稿的尺寸去開發,縮放的是整個頁面
效果預覽更高:
效果預覽更寬:
實現代碼:
新建resizeMixin.js
1 // * 默認縮放值
2 const scale = {
3 width: '1',
4 height: '1',
5 };
6
7 // * 設計稿尺寸(px)
8 const baseWidth = 1920;
9 const baseHeight = 1080;
10
11 // * 需保持的比例(默認16:9)
12 const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5));
13
14 export default {
15 data() {
16 return {
17 drawTiming: null,
18 };
19 },
20 mounted() {
21 this.calcRate();
22 window.addEventListener('resize', this.resize);
23 },
24 beforeDestroy() {
25 window.removeEventListener('resize', this.resize);
26 },
27 methods: {
28 calcRate() {
29 const appRef = this.$refs['appRef'];
30 if (!appRef) return;
31 // 當前寬高比
32 const currentRate = parseFloat(
33 (window.innerWidth / window.innerHeight).toFixed(5)
34 );
35 if (appRef) {
36 if (currentRate > baseProportion) {
37 // 表示更寬
38 scale.width = (
39 (window.innerHeight * baseProportion) /
40 baseWidth
41 ).toFixed(5);
42 scale.height = (window.innerHeight / baseHeight).toFixed(5);
43 appRef.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)`;
44 } else {
45 // 表示更高
46 scale.height = (
47 window.innerWidth /
48 baseProportion /
49 baseHeight
50 ).toFixed(5);
51 scale.width = (window.innerWidth / baseWidth).toFixed(5);
52 appRef.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)`;
53 }
54 }
55 },
56 resize() {
57 clearTimeout(this.drawTiming);
58 this.drawTiming = setTimeout(() => {
59 this.calcRate();
60 }, 200);
61 },
62 },
63 };
在app的路由下使用,body背景設置成黑色即可
1 <template>
2 <div ref="appRef">
3 <router-view />
4 </div>
5 </template>
6
7 <script>
8 import resizeMixin from '@/utils/resizeMixin ';
9
10 export default {
11 mixins: [resizeMixin]
12 }
以上就是兩種方式實現,其根本都是利用transform:scale屬性去實現的,個人僅為第二種更好理解,第一種代碼較為簡潔!