scaleScreen大屏自适应容器组件
1.引言
在做数字大屏时,需要整体页面,图表能跟着浏览器的尺寸自动变化,本文采用 vue 前端框架,采用 JavaScript 语言,封装了一个大屏自适应组件,将需要显示的页面放入组件的插槽中,就能实现自适应屏幕大小的效果。
echart引入教程:echart引入和组件封装-CSDN博客
2.实际效果
3.组件代码
scaleScreen.vue 组件
<!-- 大屏自适应容器组件 无需固定宽高 按照 window/screen比 处理, 若屏幕小于一定比列特殊处理-->
<template>
<!-- 对transform特殊处理,等比例缩放 -->
<div
class="ScaleBox"
:style="{
width: width + 'px',
height: height + 'px',
transform: `scale(${scale.w},${scale.h}) translate(-50%, -50%)`,
}"
>
<slot></slot>
</div>
</template>
<script>
/**
* 防抖函数
* @param {T} fn
* @param {number} delay
* @return
*/
function debounce(fn, delay) {
let timer = null;
return function (...args) {
timer = setTimeout(
() => {
typeof fn === "function" && fn.apply(null, args);
clearTimeout(timer);
},
delay > 0 ? delay : 100
);
};
}
export default {
data() {
return {
scale: {
//缩放比
w: 1,
h: 1,
},
width: screen.width, //宽度
height: screen.height, //高度
reCalc: null, //自适应函数
};
},
mounted() {
// 初始化时设置自适应函数
this.reCalc = debounce(() => {
this.setScale();
});
this.setScale();
this.addListener();
},
beforeDestroy() {
// 页面销毁时移除监听事件
this.clearListener();
},
methods: {
/**
* @description 获取缩放值,并特殊处理
*/
getScale() {
//缩放值 按照 window/screen 处理, 若屏幕小于一定比列特殊处理
const w = window.innerWidth / this.width;
const h = window.innerHeight / this.height;
if (window.innerWidth <= 800 || window.innerHeight <= 600) {
let scale = w < h ? w : h;
return [scale, scale];
}
return [h, w];
},
/**
* @description 设置缩放比
*/
setScale() {
// 缩放比
this.scale.h = this.getScale()[0];
this.scale.w = this.getScale()[1];
},
/**
* @description 添加resize监听事件
*/
addListener() {
window.addEventListener("resize", this.reCalc);
},
/**
* @description 移除resize监听事件
*/
clearListener() {
window.removeEventListener("resize", this.reCalc);
},
},
};
</script>
<style scoped lang="scss">
.ScaleBox {
position: absolute;
// transform: scale(v-bind('scale.w'), v-bind('scale.h')) translate(-50%, -50%);
display: flex;
flex-direction: column;
transform-origin: top left;
left: 50%;
top: 50%;
transition: 0.2s;
z-index: 999;
// background: rgba(255, 0, 0, 0.3);
}
</style>
4.使用实列
4.1 flex 布局
<!-- scaleBox + flex布局 -->
<template>
<scaleScreen class="scale-wrap">
<div
class="container p-10 flex fd-column gap-10"
:style="{
width: width + 'px',
height: height + 'px',
}"
>
<div class="header e-card"></div>
<div class="body flex flex-1 fd-column gap-10">
<div class="center flex-2 flex fd-row gap-10">
<div class="c-left flex-1 flex fd-column gap-10">
<div class="c-left1 e-card flex-1">
<radar1Chart />
</div>
<div class="c-left2 e-card flex-1">
<pie2Chart />
</div>
</div>
<div class="c-center flex-2 flex">
<div class="c-center1 e-card flex-1">
<DistributionMap />
</div>
</div>
<div class="c-right flex-1 flex fd-column gap-10">
<div class="c-right1 e-card flex-1">
<bar1Chart />
</div>
<div class="c-right2 e-card flex-1">
<line1Chart />
</div>
</div>
</div>
<div class="bottom flex-1 flex fd-row gap-10">
<div class="bottom1 e-card flex-1">
<bar2Chart />
</div>
<div class="bottom2 e-card flex-2">
<bar3Chart />
</div>
<div class="bottom3 e-card flex-1">
<pie1Chart />
</div>
</div>
</div>
</div>
</scaleScreen>
</template>
<script>
import scaleScreen from "@/components/scaleScreen";
import line1Chart from "@/examples/echart/Basics/lineChart/line1";
import line2Chart from "@/examples/echart/Basics/lineChart/line2";
import bar1Chart from "@/examples/echart/Basics/barChart/bar1";
import bar2Chart from "@/examples/echart/Basics/barChart/bar2";
import bar3Chart from "@/examples/echart/Basics/barChart/bar3";
import gauge1Chart from "@/examples/echart/Basics/gaugeChart/gauge1";
import gauge2Chart from "@/examples/echart/Basics/gaugeChart/gauge2";
import pie1Chart from "@/examples/echart/Basics/PieChart/pie1";
import pie2Chart from "@/examples/echart/Basics/PieChart/pie2";
import radar1Chart from "@/examples/echart/Basics/radarChart/radar1";
import DistributionMap from "@/examples/echart/echartMap2D/DistributionMap.vue";
export default {
components: {
scaleScreen,
line1Chart,
line2Chart,
bar1Chart,
bar2Chart,
bar3Chart,
gauge1Chart,
gauge2Chart,
pie1Chart,
pie2Chart,
radar1Chart,
DistributionMap,
},
data() {
return {
width: screen.width,
height: screen.height,
};
},
};
</script>
<style scoped lang="scss">
.e-card {
border: 2px solid;
border-image: linear-gradient(to right, #917667, #578aef) 1;
}
.container {
--header-hight: 100px;
height: 100%;
width: 100%;
background: #03213d;
/* background-image: url("../../images/bg1.jpg"); */
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
.header {
height: var(--header-hight);
}
}
</style>
4.2 grid 布局
<!-- scaleBox + grid布局 -->
<template>
<scaleScreen class="scale-wrap">
<div
class="container p-10"
:style="{
width: width + 'px',
height: height + 'px',
}"
>
<div class="header e-card"></div>
<div class="body">
<div class="center">
<div class="c-left">
<div class="c-left1 e-card"></div>
<div class="c-left2 e-card"></div>
</div>
<div class="c-center">
<div class="c-center1 e-card"></div>
</div>
<div class="c-right">
<div class="c-right1 e-card"></div>
<div class="c-right2 e-card"></div>
</div>
</div>
<div class="bottom">
<div class="bottom1 e-card"></div>
<div class="bottom2 e-card"></div>
<div class="bottom3 e-card"></div>
</div>
</div>
</div>
</scaleScreen>
</template>
<script>
import scaleScreen from "@/components/scaleScreen";
export default {
components: { scaleScreen },
data() {
return {
width: screen.width,
height: screen.height,
};
},
};
</script>
<style scoped lang="scss">
.e-card {
border: 2px solid;
border-image: linear-gradient(to right, #917667, #578aef) 1;
}
.container {
--header-hight: 100px;
height: 100%;
width: 100%;
display: grid;
grid-template-rows: var(--header-hight) auto;
row-gap: 10px;
background: #03213d;
/* background-image: url("../../images/bg1.jpg"); */
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
.header {
}
.body {
height: 100%;
display: grid;
grid-template-rows: 2fr 1fr;
row-gap: 10px;
.center {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
column-gap: 10px;
.c-left {
display: grid;
grid-template-rows: 1fr 1fr;
row-gap: 10px;
}
.c-center {
display: grid;
grid-template-rows: 1fr;
}
.c-right {
display: grid;
grid-template-rows: 1fr 1fr;
row-gap: 10px;
}
}
.bottom {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
column-gap: 10px;
}
}
}
</style>