uniapp實現帶過渡動畫的手風琴摺疊樣式

最終效果

UI同學讓做一個帶過渡動畫的手風琴摺疊效果,點擊一個元素展開,其他已展開元素自動收縮,每次最多隻有一個元素展開,這是最終效果:
在這裏插入圖片描述
接下來講我用css實現的思路

一、無過渡動畫的手風琴

首先,uniapp做無過渡動畫的最容易做了,因爲Vue裏只要用v-ifv-show來控制,判斷index是否是當前的子組件就好了。因爲我用了組件,我想父組件的事件openDetail觸發能更新子組件的數據,所以我用:ref來更新子組件的boolean變量isOpen來觸發v-show="isOpen",記錄lastIndex來關閉上個展開的子組件,確保每次點擊最多隻有一個展開。
父組件

<view>
	<collapse-item v-for="(item, index) in list" :key="index" 
		@tap="openDetail(index)" :ref="'collapse'+index"
	</collapse-item>
</view>
...
<script>
export default {
	data() {
		return {
			lastIndex: -1;
		}
	},
	methods: {
		// 手風琴式收縮展示offer列表
		if (index != this.lastIndex && this.lastIndex >= 0) {
			this.$refs['collapse'+this.lastIndex][0].isOpen = false;
			this.$refs['collapse'+index][0].isOpen = !this.$refs['collapse'+index][0].isOpen;
		} else {
			this.$refs['collapse'+index][0].isOpen = !this.$refs['collapse'+index][0].isOpen;
		}
		this.lastIndex = index;
	}
}
</script>

子組件collapse-item

<view v-show="isOpen">
	<view>專業</view>
	<view>均分</view>
	<view>入學</view>
</view> 
...
export default {
	data() {
		return {
			isOpen: false,
		}
	},
}	

二、有過渡動畫的手風琴

現在來做過渡動畫,我在做的時候,發現有以下幾點需要注意:

1. 不能再用v-if或v-show

過渡動畫的css實現大家肯定能想到是transition,而transition的動畫是基於兩個狀態的來回變化的,不管是v-if的增刪DOM節點還是v-show的display: none都是隻有一個狀態,無法滿足前後兩個狀態,transition會失效。

2. 用:class動態綁定樣式

可以用 :class的對象語法:class="isOpen ? 'content-open' : 'content-close'"來動態綁定展開和收起兩種狀態的樣式。
展開狀態設置高度height值,而收起狀態設height爲0,兩個狀態都設置transition,就能實現過渡動畫。

我們來更新一下子組件collapse-item的代碼:

<view :class="isOpen ? 'content-open' : 'content-close'">
	<view :style="{height: isOpen ? '40rpx' : '0'}">專業</view>
	<view :style="{height: isOpen ? '40rpx' : '0'}">均分</view>
	<view :style="{height: isOpen ? '40rpx' : '0'}">入學</view>
</view> 
...
export default {
	data() {
		return {
			isOpen: false,
		}
	},
}	
...
<style>
.content-open {
	height: 180 rpx;
	transition: all 0.4s cubic-bezier(0.25, 1.0, 0.25, 1.0);
}
.content-close {
	height: 0;
	transition: all 0.4s cubic-bezier(0.25, 1.0, 0.25, 1.0);
}
</style>

3. 子元素也要設置transition

寫完上面的代碼以後,我發現了一個問題,文字出現的比背景顏色快,在背景顏色還沒有過渡動畫展開完時,文字就已經全出現了,而且文字並沒有像我預想一樣的也有展開動畫效果。

在這裏插入圖片描述
問題雖然不大,但是視覺上給人的體驗非常不好,所以我一定要解決。

正當我無比困惑時,我突然想到,是不是transition屬性無法繼承?
我就查了一下W3C文檔:https://drafts.csswg.org/css-transitions/

在這裏插入圖片描述
果然transitioninherited:no,無法繼承的。
所以我們子元素也都要設置transition,才能達到背景顏色和文字同時有過渡動畫的展開和收起的效果。
再更新一下子組件的代碼:

<view :class="isOpen ? 'content-open' : 'content-close'">
	<view :class="isOpen ? 'item-open' : 'item-close'">專業</view>
	<view :class="isOpen ? 'item-open' : 'item-close'">均分</view>
	<view :class="isOpen ? 'item-open' : 'item-close'">入學</view>
</view> 
...
export default {
	data() {
		return {
			isOpen: false,
		}
	},
}	
...
<style>
.content-open {
	height: 180 rpx;
	overflow: hidden;
	transition: all 0.4s cubic-bezier(0.25, 1.0, 0.25, 1.0);
}
.content-close {
	height: 0;
	transition: all 0.4s cubic-bezier(0.25, 1.0, 0.25, 1.0);
}
.item-open {
	height: 40rpx;
	transition: all 0.4s cubic-bezier(0.25, 1.0, 0.25, 1.0);
}
.item-close {
	opacity: 0;
	height: 0;
}
</style>

content-open裏設置overflow: hidden,展開時文字就不會浮在下一個元素上。
至於我爲什麼子元素的item-close不設置transition 呢,因爲三行文字先會縮成一行重疊的字再消失,太醜了,大家試試就知道了,所以乾脆文字在close時直接消失好了~

我們的帶過渡動畫的手風琴摺疊效果就做好啦,效果和文章開頭的圖一樣~

覺得有用的請點個贊,謝謝大家的觀看~轉載請帶本文鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章