uniapp定義動(dòng)畫的幾種方式總結(jié)
本章的前提就是大家都知道動(dòng)畫的基本屬性,例如animation-name
、animation-duration
、animation-timing-function
、animation-delay
、animation-iteration-count
和animation-direction
屬性。
了解更多 animation 相關(guān)的內(nèi)容。
現(xiàn)在制作一個(gè)左右抖動(dòng)的動(dòng)畫效果,效果如下:
在 uniapp 中,可以通過如下兩種方式來完成。
1. 直接使用 CSS 動(dòng)畫
1.1 定義動(dòng)畫
@keyframes shakeX { from, to { transform: translate3d(0, 0, 0); } 10%, 30%, 50%, 70%, 90% { transform: translate3d(-10px, 0, 0); } 20%, 40%, 60%, 80% { transform: translate3d(10px, 0, 0); } } .shakeX { animation-name: shakeX; animation-duration: 1s; }
1.2 使用
<view class="box shakeX"></view> <style> .box { width: 100rpx; height: 100rpx; background-color: green; } </style>
效果如下:
2. 通過 uniapp 提供編程式創(chuàng)建動(dòng)畫
uniapp 提供 createAnimation
內(nèi)置函數(shù),用于創(chuàng)建一個(gè)動(dòng)畫實(shí)例 animation。
動(dòng)畫定義步驟:
- 創(chuàng)建動(dòng)畫實(shí)例
- 調(diào)用實(shí)例的方法來描述動(dòng)畫
- 通過動(dòng)畫實(shí)例的
export
方法導(dǎo)出動(dòng)畫數(shù)據(jù) - 導(dǎo)出的動(dòng)畫數(shù)據(jù)傳遞給組件的
animation
屬性(uniapp 提供組件都支持 animation 屬性)
兼容性列表:
App | H5 | 微信小程序 | 支付寶小程序 | 百度小程序 | 字節(jié)跳動(dòng)小程序、飛書小程序 | QQ小程序 | 快手小程序 | 京東小程序 | |
---|---|---|---|---|---|---|---|---|---|
√ | HBuilderX 2.0.4+ | √ | √ | √ | √ | √ | x | x |
注意??:
export
方法每次調(diào)用后會(huì)清掉之前的動(dòng)畫操作。nvue
暫不支持
2.1 定義動(dòng)畫
接下來通過編程實(shí)現(xiàn)上面抖動(dòng)功能。
2.1.1 創(chuàng)建動(dòng)畫實(shí)例
const animation = uni.createAnimation(); // 定義動(dòng)畫實(shí)例
2.1.2 調(diào)用實(shí)例方法來描述動(dòng)畫
在上面的 shakeX
動(dòng)畫定義中,通過 translate3d
來定義動(dòng)畫。 對(duì)應(yīng)的在 animation
實(shí)例中去查找與 translate3d
相關(guān)的實(shí)例方法。
translate
相關(guān)的實(shí)例方法,如下:
方法 | 參數(shù) | 說明 |
---|---|---|
translate | tx,[ty] | 一個(gè)參數(shù)時(shí),表示在X軸偏移tx,單位px;兩個(gè)參數(shù)時(shí),表示在X軸偏移tx,在Y軸偏移ty,單位px。 |
translateX | tx | 在X軸偏移tx,單位px |
translateY | ty | 在Y軸偏移ty,單位px |
translateZ | tz | 在Z軸偏移tz,單位px |
translate3d | (tx,ty,tz) | 在X軸偏移tx,在Y軸偏移ty,在Z軸偏移tz,單位px |
有了這些方法之后,我們可以描述動(dòng)畫啦~
@keyframes shakeX { from, to { transform: translate3d(0, 0, 0); } 10%, 30%, 50%, 70%, 90% { transform: translate3d(-10px, 0, 0); } 20%, 40%, 60%, 80% { transform: translate3d(10px, 0, 0); } }
上面 CSS 中 translate3d
,對(duì)應(yīng)到編程方式如下:
animation.translate3d(0, 0, 0); // 原始位置 animation.translate3d(-10, 0, 0); // 向左偏移 animation.translate3d(10, 0, 0); // 像右偏移
有上面方法后,可以把動(dòng)畫描述出來,如下:
animation.animation3d(0, 0, 0) // 0% .animation3d(-10, 0, 0) // 10% .animation3d(10, 0, 0) // 20% .animation3d(-10, 0, 0) // 30% // ... .animation3d(0, 0, 0); // 100%
現(xiàn)在通過 export()
方法導(dǎo)出定義動(dòng)畫:
<template> <view class="box" :animation="animationData"></view> </template>
export default { data() { return { animationData: {} } }, onLoad(){ const animation = uni.createAnimation(); animation.animation3d(0, 0, 0) // 0% .animation3d(-10, 0, 0) // 10% .animation3d(10, 0, 0) // 20% .animation3d(-10, 0, 0) // 30% // ... .animation3d(0, 0, 0); // 100% this.animationData = animation.export(); } }
代碼運(yùn)行之后,并沒有如期出現(xiàn)預(yù)期抖動(dòng)效果。為什么? 因?yàn)?nbsp;uniapp
中在定義的一組動(dòng)畫中是并行執(zhí)行的,所以并不會(huì)產(chǎn)生動(dòng)畫效果。
再回過來,看上面 CSS 中把一個(gè)動(dòng)畫周期劃分成不同的組(步驟),10%
時(shí)執(zhí)行 translate3d(-10px, 0, 0)
,20%
時(shí)執(zhí)行translate3d(10px, 0, 0)
。
在 uni-app 中有沒有類似的方式呢? 通過 step
來定義。
animation .translateX(0) // 0% .translateX(10) // 20% .step(); animation.translateX(-10).step(); // 30% animation.translateX(10).step(); // 40% animation.translateX(-10).step(); // 50% animation.translateX(10).step(); // 60% animation.translateX(-10).step(); // 70% animation.translateX(10).step(); // 80% animation.translateX(-10).step(); // 90% animation.translateX(0).step(); // 100% this.animationData = animation.export();
再來執(zhí)行代碼,發(fā)現(xiàn)會(huì)動(dòng)了。
從效果來看發(fā)現(xiàn)跟預(yù)期效果差很多,為什么? 跟 animation 的 animation-duration
屬性有關(guān)。
animation-duration
: 屬性指定一個(gè)動(dòng)畫周期的時(shí)長。
也就是一組動(dòng)畫運(yùn)行完所需時(shí)間。 在 uni.createAnimation()
創(chuàng)建動(dòng)畫時(shí)可以傳遞參數(shù),在不顯示的指定 duration
值時(shí),默認(rèn)值為 400ms
。 而 step()
會(huì)繼承該值。
參數(shù) | 類型 | 必填 | 默認(rèn)值 | 說明 | |
---|---|---|---|---|---|
duration | Integer | 否 | 400 | 動(dòng)畫持續(xù)時(shí)間,單位ms | |
timingFunction | String | 否 | "linear" | 定義動(dòng)畫的效果 | |
delay | Integer | 否 | 0 | 動(dòng)畫延遲時(shí)間,單位 ms | |
transformOrigin | String | 否 | "50% 50% 0" | 設(shè)置transform-origin |
這就是 “慢” 的原因。
在明白“慢”之后,只要把動(dòng)畫執(zhí)行時(shí)間 (duration) 調(diào)整,應(yīng)該能看到預(yù)期效果。假設(shè)期望完成抖動(dòng)時(shí)間 1s
,把動(dòng)畫拆分成 10
組,則每一組的動(dòng)畫時(shí)間為 100 ms
.
現(xiàn)在指定 step
的 duration
值為 100ms
,更改后代碼如下:
animation .translateX(0) // 0% .translateX(10) // 20% .step({ duration: 100, }); animation.translateX(-10).step({ duration: 100, }); // 30% animation.translateX(10).step({ duration: 100, }); // 40% animation.translateX(-10).step({ duration: 100, }); // 50% animation.translateX(10).step({ duration: 100, }); // 60% animation.translateX(-10).step({ duration: 100, }); // 70% animation.translateX(10).step({ duration: 100, }); // 80% animation.translateX(-10).step({ duration: 100, }); // 90% animation.translateX(0).step({ duration: 100, }); this.animationData = animation.export();
再來執(zhí)行代碼,運(yùn)行效果如下:
發(fā)現(xiàn)效果基本與預(yù)期效果一樣了。
更多 uni.createAnimation()
相關(guān)的內(nèi)容,可以自行查看文檔
3. 什么情況下使用編程式創(chuàng)建動(dòng)畫
當(dāng)不能通過 css
方式或通過動(dòng)態(tài)類名一些方式去添加動(dòng)畫時(shí),此時(shí)就可以考慮使用編程式來創(chuàng)建動(dòng)畫。編程式可以很靈活創(chuàng)建動(dòng)畫、控制動(dòng)畫運(yùn)行和監(jiān)聽動(dòng)畫的結(jié)束。 其次從兼容列表來看,能很好在不同平臺(tái)運(yùn)行。
現(xiàn)在看個(gè)實(shí)際例子: 在登錄時(shí),通常需要 ?? 選用戶協(xié)議和隱私政策 之后才允許用戶登錄。現(xiàn)在產(chǎn)品希望當(dāng)用戶在未勾選時(shí)點(diǎn)擊登錄,希望通過抖動(dòng) 用戶協(xié)議和隱私政策來提醒用戶。
上面需求需要完成幾個(gè)功能點(diǎn):
- 定義抖動(dòng)動(dòng)畫類
- 未勾選時(shí)動(dòng)態(tài)添加動(dòng)畫類
- 動(dòng)畫結(jié)束時(shí)移除動(dòng)畫類(用戶下一次點(diǎn)擊時(shí),需要繼續(xù)抖動(dòng))
通??梢赃@樣做:
<view ref="agreement" class="agreement" :class="{ 'shakeX': actived }"> <radio @click="onChecked" style="transform: scale(0.6)" :color="color" :checked="agreement" ></radio> 我已閱讀并同意<text class="service" >用戶協(xié)議</text >和<text class="privacy">隱私政策</text> </view> <button @click="onLogin">登錄</button>
export default { data() { return { actived: false // false }; }, mounted(){ this.$refs.agreement.$el.addEventListener("animationend", ()=> { this.actived = false; // 動(dòng)畫結(jié)束移除類 }); }, methods: { onLogin(){ // 動(dòng)態(tài)添加 this.actived = true; } }, };
@keyframes shakeX { from, to { transform: translate3d(0, 0, 0); } 10%, 30%, 50%, 70%, 90% { transform: translate3d(-10px, 0, 0); } 20%, 40%, 60%, 80% { transform: translate3d(10px, 0, 0); } } .shakeX { animation-name: shakeX; animation-duration: 1s; }
發(fā)現(xiàn)在 app
、小程序
上運(yùn)行時(shí),發(fā)現(xiàn) this.$refs.agreement.$el
為空,這是為什么,這里就是跟 uniapp 底層設(shè)計(jì)有關(guān),如下圖所示:
上面引用微信小程序,uniapp 在設(shè)計(jì)跟小程序是一樣的。 也可以在上底層設(shè)計(jì)鏈接中了解到 uniapp
設(shè)計(jì)。
如果不能獲取元素并注冊(cè)animationend
事件,沒辦法很好知道動(dòng)畫結(jié)束,不知道何時(shí)應(yīng)該移除。當(dāng)然有的人想可以通過定時(shí)器完成,這樣不能精細(xì)話控制。
此時(shí)通過編程式就可以很好解決兼容的問題,現(xiàn)在稍微調(diào)整下:
<view class="agreement" :animation="animationData"> <radio @click="onChecked" style="transform: scale(0.6)" :color="color" :checked="agreement" ></radio> 我已閱讀并同意<text class="service" >用戶協(xié)議</text >和<text class="privacy">隱私政策</text> </view> <button @click="onLogin">登錄</button>
export default { data() { return { animationData: {} }; }, onLoad(){ const animation = uni.createAnimation({ timingFunction: "linear", }); this.animation = animation; }, methods: { shakeX() { const animation = this.animation; animation .translateX(0) // 0% .translateX(10) // 20% .step({ duration: 100, }); animation.translateX(-10).step({ duration: 100, }); // 30% animation.translateX(10).step({ duration: 100, }); // 40% animation.translateX(-10).step({ duration: 100, }); // 50% animation.translateX(10).step({ duration: 100, }); // 60% animation.translateX(-10).step({ duration: 100, }); // 70% animation.translateX(10).step({ duration: 100, }); // 80% animation.translateX(-10).step({ duration: 100, }); // 90% animation.translateX(0).step({ duration: 100, }); this.animationData = animation.export(); }, onLogin(){ this.shakeX(); } }, };
通過編程方式,為什么不需要像動(dòng)態(tài)類名的方式,動(dòng)畫結(jié)束必須移除類名否則下次不會(huì)生效? 這里留給大家去思考了。
4. 總結(jié)
- 具體采用哪種方式創(chuàng)建動(dòng)畫,可以根據(jù)實(shí)際業(yè)務(wù)場景來定。
- uniapp 編程方式,通過
step
來進(jìn)行動(dòng)畫分組,同一個(gè)分組內(nèi)動(dòng)畫函數(shù)會(huì)并行執(zhí)行。 - 多個(gè)動(dòng)畫分組之間的執(zhí)行是串行的,也就是需等待上一個(gè)結(jié)束才會(huì)執(zhí)行下一個(gè)。
到此這篇關(guān)于uniapp定義動(dòng)畫的幾種方式的文章就介紹到這了,更多相關(guān)uniapp定義動(dòng)畫方式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javascript 阿拉伯?dāng)?shù)字轉(zhuǎn)化中國大寫數(shù)字的函數(shù)代碼
將阿拉伯?dāng)?shù)字轉(zhuǎn)化中國大寫數(shù)字的函數(shù)代碼,需要的朋友可以參考下。2010-04-04詳解JavaScript基于面向?qū)ο笾^承實(shí)例
這篇文章主要介紹了JavaScript基于面向?qū)ο笾^承實(shí)例,需要的朋友可以參考下2015-12-12JS判斷傳入函數(shù)的參數(shù)是否為空(函數(shù)參數(shù)是否傳遞)
這篇文章主要介紹了JS判斷傳入函數(shù)的參數(shù)是否為空(函數(shù)參數(shù)是否傳遞),需要的朋友可以參考下2023-05-05js 函數(shù)的執(zhí)行環(huán)境和作用域鏈的深入解析
在js中對(duì)象的外在表現(xiàn)形式為函數(shù)。2009-11-11JavaScript實(shí)現(xiàn)鼠標(biāo)移動(dòng)事件畫筆
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)鼠標(biāo)移動(dòng)事件畫筆,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08