scaleScreen大屏自适应容器组件

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>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值