Flex布局下居中滚动溢出截断处理

Flex布局下居中滚动溢出截断处理_第1张图片
摘要:

遇到一个需求,在uniapp swiper下实现轮播图,图片的高度是自适应的,超出屏幕设备的高度的时候,滚动显示全部,图片的高度没有超过屏幕的高度时候,上下居中于屏幕的中间!下面写了个dome来研究一下这!

画出dome: justify-content: center;居中对齐
超过屏幕宽度的时候居中对齐的1被吃掉了,但是8正常的!如果没有超出屏幕的时候屏幕居中对齐的!
Flex布局下居中滚动溢出截断处理_第2张图片

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>拖拽</title>
		<style>
			body {
				margin: 0;
				padding: 0;
			}

			.product-status {
				width: 100%;
				font-size: 30px;
			}

			.other {
				display: flex;
				width: 100%;
				overflow-x: scroll;
				/* 修改justify-content居中不居中 */
				justify-content: center;
				gap: 10px;
			}

			.other div {
				padding: 0 100px;
				height: 200px;
				background: red;
				display: flex;
				align-items: center;
				justify-content: center;
			}
		</style>
	</head>
	<body>
		<div class="product-status">
			超出:
			<div class="other">
				<div>1</div>
				<div>2</div>
				<div>3</div>
				<div>4</div>
				<div>5</div>
				<div>6</div>
				<div>7</div>
				<div>8</div>
			</div>
			
			不超出:
			<div class="other">
				<div>1</div>
				<div>2</div>
			</div>
		</div>
		<script>
			window.onload = function() {

			}
		</script>
	</body>
</html>

方法一:Flex 布局下关键字 safe、unsafe但是版本要求高
在从 Chrome 115 开始,flex 布局下新增了两个关键字 safe 和 unsafe。

Flex布局下居中滚动溢出截断处理_第3张图片
将 justify-content: center 改为 justify-content: safe center 即可:但是不满足我这的开发需求,记录一下!
目前而言,这个方法唯一的问题在于 兼容性,safe 关键字的大范围使用,还需要静待一段时间。

.other {
	display: flex;
	width: 100%;
	overflow-x: scroll;
	/* 修改justify-content居中不居中 */
	justify-content: safe center;
	gap: 10px;
}

方法二:使用 margin: auto 替代 justify-content: center

.other {
	display: flex;
	width: 100%;
	overflow-x: scroll;
	/* 修改justify-content居中不居中 */
	/* justify-content: center; */
	gap: 10px;
}

.other div {
	padding: 0 100px;
	height: 200px;
	background: red;
	margin: auto;
	/* display: flex;
	align-items: center;
	justify-content: center; */
}

这方案超过的就正常了,但是没有超过的就自动根据占位来自动平分了!还是不能满足要求,记录一下!
Flex布局下居中滚动溢出截断处理_第4张图片

用规范的话说就是,设置了 margin: auto 的元素,在通过 justify-content 和 align-self 进行对齐之前,任何正处于空闲的空间都会分配到该方向的自动 margin 中去。

方法三:额外嵌套一层
上面的 margin:auto 虽然没有兼容性问题,但是有一点点瑕疵。我们仔细对比 margin: auto 与 justify-content: center 在 flex-item 不足以溢出下的表现:
瑕疵在于,使用 margin: auto 的方式,flex-item 之间的间距是不可控。因为它们始终会去平分剩余空余空间。
所以,兼容性最好的方式,就是我们多叠加一层,同样可以巧妙的解决这个问题。

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>拖拽</title>
		<style>
			body {
				margin: 0;
				padding: 0;
			}

			.product-status {
				width: 100%;
				font-size: 30px;
			}

			.other {
				width: 100%;
				height: 300px;
				position: relative;
				margin: auto;
				display: flex;
				flex-wrap: nowrap;
				flex-direction: row;
				justify-content: center;
				align-items: center;
				overflow: auto;
				/* counter-reset: myCounter; */
			}

			.other_item {
				display: flex;
				gap: 10px;
				max-width: 100%;
			}
			.other_item div {
				width: 200px;
				height: 300px;
				background: red;
				position: relative;
				flex-shrink: 0;
				background: red;
				/* &::before {
				    counter-increment: myCounter;
				    content: counter(myCounter);
				    inset: 0;
				    position: absolute;
				    text-align: center;
				} */
			}
		</style>
	</head>
	<body>
		<div class="product-status">
			超出:
			<div class="other">
				<div class="other_item">
					<div>1</div>
					<div>2</div>
					<div>3</div>
					<div>4</div>
					<div>5</div>
					<div>6</div>
					<div>7</div>
					<div>8</div>
				</div>
			</div>
			
			不超出:
			<div class="other">
				<div class="other_item">
					<div>1</div>
					<div>2</div>
				</div>
			</div>
		</div>
		<script>
			window.onload = function() {

			}
		</script>
	</body>
</html>

Flex布局下居中滚动溢出截断处理_第5张图片

参考网站W3C:Cascading Style Sheets
Flex布局下居中滚动溢出截断处理_第6张图片

回到需求中:

uniapp swiper下实现轮播图,图片的高度是自适应的,超出屏幕设备的高度的时候,滚动显示全部,图片的高度没有超过屏幕的高度时候,上下居中于屏幕的中间!
Flex布局下居中滚动溢出截断处理_第7张图片

上面的研究还真的不符合需求的!但会用到是,因为这里嵌套了swiper的多层view,拿不到swiper中间的视图父子之间的dome关系层!所以这里常用逻辑的处理方法!

思路:
设置基础的可高度为100vh,以这为基础来动态获取屏幕的可视化高度与动态图片高度作为对比,浏览器中当图片的高度填满屏幕的100vh的时候,证明已经超过可视化的高度,所以当他们相等的时候去掉默认的弹性布局让图片动态高度作为滚动的基础溢出屏幕隐藏滚动!真机中当图片高度大于等于屏幕的高度的时候去掉弹性布局让图片动态高度作为滚动的基础溢出屏幕隐藏滚动!

<template>
	<view class="imageView">
		<view class="imageContent">
			<view class="imageItem">
				<swiper @change="changeSwiper" class="imageContainer" :current="current" indicator-dots>
					<swiper-item v-for="(item, index) in imageList" :key="index" :class="classType == 0 ? 'flexCenter' : ''" class="swiperitem">
						<image style="width: 100%;" :id="'itemImg' + index" :class="current == index ? 'swiperactive' : ''" :src="item" lazy-load mode="widthFix"></image>
						<!-- <scroll-view 
						  scroll-y="true" 
						  style="height: 100%;"
						  :class="classType == 0 ? 'flexCenter' : ''">
							<image style="width: 100%;" :id="'itemImg' + index" :class="current == index ? 'swiperactive' : ''" :src="item" lazy-load mode="widthFix"></image>
					    </scroll-view> -->
					</swiper-item>
				</swiper>
			</view>
			<view class="callIt">长按保存图片</view>
		</view>
	</view>
</template>

<script>
	export default {
		name: "imageView",
		mounted() {
			this.windowHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
			this.imageList = uni.getStorageSync('iamgeList');
			setTimeout(() => {
				this.setSwiperHeight();
			}, 2000)
		},
		data() {
			return {
				imageList: [],
				current: 0,
				swiperHeight: null,
				currentIndex: 0,
				windowHeight: null,
				classType: 0
			}
		},
		methods: {
			changeSwiper(e) {
				this.current = e.detail.current;
				this.$nextTick(() => {
					this.setSwiperHeight();
				});
			},
			setSwiperHeight() {
				let that = this;
				let element = "#itemImg" + that.current;
				let query = uni.createSelectorQuery().in(that);
				query.select(element).boundingClientRect();
				query.exec((res) => {
					if (res && res[0]) {
						that.swiperHeight = res[0].height;
						//if (that.swiperHeight == that.windowHeight) {
						//浏览器会取一个精度值的
						if (that.swiperHeight >= that.windowHeight) {
							that.classType = 1;
						}
					}
				})
			}
		}
	}
</script>

<style lang="less" scoped>
	.flexCenter {
		display: flex;
		align-items: center;
		flex-direction: column;
		justify-content: center;
	}

	.imageView {
		height: 100vh;
		width: 100%;
		background: #000;

		.imageContent {
			width: 100%;
			height: 100vh;
			background: #000;

			.imageItem {
				width: 100%;
				height: 100vh;

				.imageContainer {
					width: 100%;
					height: 100%;

					.swiperitem {
						width: 100%;
						height: 100%;
						overflow: scroll;
					}
				}
			}

			.callIt {
				width: 32vw;
				background: #999;
				color: #fff;
				text-align: center;
				padding: 1.2vw;
				position: absolute;
				bottom: 35vw;
				border-radius: 10vw;
				left: 50%;
				transform: translateX(-50%);
			}
		}
	}
</style>

你可能感兴趣的:(JAVASCRIPT,UNIAPP,CSS,前端,vue.js,javascript)