天天看點

uniapp實作帶過渡動畫的手風琴折疊樣式

目錄

    • 最終效果
    • 一、無過渡動畫的手風琴
    • 二、有過渡動畫的手風琴
      • 1. 不能再用v-if或v-show
      • 2. 用:class動态綁定樣式
      • 3. 子元素也要設定transition

最終效果

UI同學讓做一個帶過渡動畫的手風琴折疊效果,點選一個元素展開,其他已展開元素自動收縮,每次最多隻有一個元素展開,這是最終效果:

uniapp實作帶過渡動畫的手風琴折疊樣式

接下來講我用css實作的思路

一、無過渡動畫的手風琴

首先,uniapp做無過渡動畫的最容易做了,因為Vue裡隻要用

v-if

v-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

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

uniapp實作帶過渡動畫的手風琴折疊樣式

問題雖然不大,但是視覺上給人的體驗非常不好,是以我一定要解決。

正當我無比困惑時,我突然想到,是不是

transition

屬性無法繼承?

我就查了一下W3C文檔:https://drafts.csswg.org/css-transitions/

uniapp實作帶過渡動畫的手風琴折疊樣式

果然

transition

inherited: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時直接消失好了~

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

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