0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何使用屬性動(dòng)畫(huà)實(shí)現(xiàn)簡(jiǎn)單屬性變化的動(dòng)畫(huà)效果

OpenAtom OpenHarmony ? 來(lái)源:OpenAtom OpenHarmony ? 作者:OpenAtom OpenHarmony ? 2022-09-29 09:44 ? 次閱讀

一、簡(jiǎn)介

繼《OpenHarmony有氧拳擊設(shè)備端的開(kāi)發(fā)》后,本次為大家?guī)?lái)酷炫的應(yīng)用端開(kāi)發(fā)。如下視頻,開(kāi)發(fā)者伴隨著音樂(lè),律動(dòng)出拳后,那開(kāi)發(fā)板屢屢播放“挨打”效果,這究竟是怎么一回事?讓我們一探背后原理。 這款拳擊游戲開(kāi)始時(shí)會(huì)播放音樂(lè),然后以隨機(jī)速度下落“擊拳方塊”。當(dāng)小哥哥在擊拳區(qū)域內(nèi)揮拳時(shí),游戲會(huì)判斷方塊的位置,根據(jù)不同位置確定播放普通擊中或完美擊中的動(dòng)畫(huà)效果。

5f75193c-3f2f-11ed-9e49-dac502259ad0.png

二、動(dòng)畫(huà)

游戲中一共使用兩種動(dòng)畫(huà):屬性動(dòng)畫(huà)和Lottie動(dòng)畫(huà),分別實(shí)現(xiàn)下落和擊中的效果?!皳羧綁K”下落效果是利用屬性動(dòng)畫(huà)進(jìn)行修改偏移量來(lái)實(shí)現(xiàn)。游戲同時(shí)設(shè)置定時(shí)器,定時(shí)獲取揮拳狀態(tài)和“擊拳方塊”的所處位置,用于判斷當(dāng)前揮拳是否得分。若得分則根據(jù)擊中區(qū)間來(lái)播放不同效果的Lottie動(dòng)畫(huà)。

三、“下落”動(dòng)畫(huà)

5fc85f84-3f2f-11ed-9e49-dac502259ad0.gif

1、屬性動(dòng)畫(huà)介紹

從上圖可以看到,游戲中“擊拳方塊”是自上而下勻速移動(dòng)。這種簡(jiǎn)單控制通用屬性進(jìn)行動(dòng)畫(huà)變化的動(dòng)畫(huà),便很適合使用屬性動(dòng)畫(huà)來(lái)實(shí)現(xiàn)。屬性動(dòng)畫(huà)是指組件的通用屬性發(fā)生變化時(shí),會(huì)根據(jù)開(kāi)始狀態(tài)和通用屬性改變后的狀態(tài)作為動(dòng)畫(huà)關(guān)鍵幀,在指定時(shí)間內(nèi)實(shí)現(xiàn)漸變效果。換言之我們只需要確定設(shè)置好組件在動(dòng)畫(huà)結(jié)束時(shí)的組件屬性,然后調(diào)用animateTo(value: AnimationOptions, event: ()=> void),即可創(chuàng)建屬性動(dòng)畫(huà)。

AnimationOptions對(duì)象說(shuō)明

● 屬性

62f4e4ca-3f2f-11ed-9e49-dac502259ad0.png

接口

6316b8a2-3f2f-11ed-9e49-dac502259ad0.png

2、動(dòng)畫(huà)實(shí)現(xiàn)

編寫(xiě)“擊拳方塊”UI組件,并將組件的相對(duì)布局偏移量offset屬性,綁定到@state leftY1變量中,那么通過(guò)修改leftY1的值即可實(shí)現(xiàn)修改組件所在位置。

@State leftY1: string = '50%'    @Builder LeftBoxing(offsetY: string) {        Image($r('app.media.icon_boxing_left'))            .width(144)            .height(110)            .offset({ x: "-30%", y: offsetY })            .touchable(true)    }    build() {        Stack() {            // .....             // 左側(cè)            this.LeftBoxing(this.leftY1)            // .....}

632fd616-3f2f-11ed-9e49-dac502259ad0.gif

3、創(chuàng)建動(dòng)畫(huà)

調(diào)用animateTo顯式動(dòng)畫(huà)來(lái)播放動(dòng)畫(huà)實(shí)現(xiàn)單個(gè)“擊拳方塊”自上而下地移動(dòng),再通過(guò)設(shè)置delay參數(shù)實(shí)現(xiàn)4個(gè)“擊拳方塊”按順序分別移動(dòng)。

    async leftAnimate(){        // 設(shè)置圖標(biāo)下滑動(dòng)畫(huà)        // 動(dòng)畫(huà)持續(xù)時(shí)間        let leftDuration = this.getRandomDuration()        this.leftDuration = leftDuration        // 延遲時(shí)長(zhǎng)        let leftDelay = leftDuration / (this.boxingCount - 1)        // 設(shè)置開(kāi)始時(shí)間        let now = new Date        this.animateLeftTimestamp = now.getTime()        // 左側(cè)animateTo動(dòng)畫(huà)        animateTo({ duration: leftDuration, curve: Curve.Linear,delay:0 * leftDelay ,iterations: 1 }, () => {            this.leftY1 = "50%"        })        animateTo({ duration: leftDuration, curve: Curve.Linear,delay:1 * leftDelay, iterations: 1 }, () => {            this.leftY2 = "50%"        })        animateTo({ duration: leftDuration, curve: Curve.Linear,delay:2 * leftDelay, iterations: 1 }, () => {            this.leftY3 = "50%"        })        animateTo({ duration: leftDuration, curve: Curve.Linear,delay:3 * leftDelay, iterations: 1 }, () => {            this.leftY4 = "50%"        })        let totalTime = leftDuration + 3 * leftDelay        await this.sleep(totalTime)        this.resetAnimate(true)        this.leftAnimate()}

6488174e-3f2f-11ed-9e49-dac502259ad0.gif

4、設(shè)置擊中區(qū)域監(jiān)聽(tīng)

設(shè)置定時(shí)器定時(shí)查詢(xún)當(dāng)前是否揮拳,若檢測(cè)到揮拳再通過(guò)計(jì)算當(dāng)前動(dòng)畫(huà)運(yùn)行時(shí)間來(lái)判斷“擊拳方塊”位置,從而執(zhí)行擊中或完美擊中的邏輯,以下為監(jiān)聽(tīng)邏輯。

    setScoreListen(){        this.intervalNumber = setInterval(async()=>{            let res = await BoxingGameNAPI.recvMsg();            if(res?.message.length > 0){                if(res.message.includes('left') && !this.leftAnimateLock){                    // 檢測(cè)到左手揮拳                    this.judgeLeft()                }            }        },200)    }
    judgeLeft(){        let nowTime = new Date().getTime()        // 首次抵達(dá)目標(biāo)頂部時(shí)間        let firstTime = this.animateLeftTimestamp + (this.percentToPoint(this.targetOffsetY)+this.percentToPoint('50%') - this.percentToPoint('10%')) * this.leftDuration        // 結(jié)束時(shí)間        let endTime = this.animateLeftTimestamp + this.leftDuration * 2        if(nowTime > firstTime - 200 && nowTime < endTime){            // 得分時(shí)間界限            let leftDelay =  this.leftDuration /(this.boxingCount -1 )            let handleTime = (nowTime - firstTime) % leftDelay            let judgeTime = this.leftDuration /6            CommonLog.info(TAG,`leftDelay:${leftDelay},handleTime:${handleTime},judgeTime:${judgeTime}`)            // 完美擊中            if (judgeTime/4 < handleTime && handleTime  < (judgeTime *(3/4))) {                            }else if(handleTime < judgeTime){               // 普通擊中            }else{                // 不得分            }        }else{            // 未抵達(dá)區(qū)域        }????}

四、擊中動(dòng)畫(huà)

64fc4326-3f2f-11ed-9e49-dac502259ad0.gif

像前文提到的“下落”動(dòng)畫(huà)適合使用屬性動(dòng)畫(huà),那么當(dāng)我們需要實(shí)現(xiàn)更復(fù)雜,如上圖的動(dòng)畫(huà)效果時(shí),該如何來(lái)實(shí)現(xiàn)呢?

Lottie介紹

Lottie是一款能夠?yàn)閼?yīng)用程序添加動(dòng)畫(huà)的開(kāi)源組件,它可以解析AE(After Effects)導(dǎo)出的json文件,讓復(fù)雜的動(dòng)畫(huà)資源輕松運(yùn)行在應(yīng)用程序中。如圖所示,動(dòng)畫(huà)文件通過(guò)AE的bodymovin插件將動(dòng)畫(huà)轉(zhuǎn)換成通用的json格式描述文件后,應(yīng)用開(kāi)發(fā)者只需使用Lottie解析json文件,就能將動(dòng)畫(huà)繪制出來(lái)。

Lottie優(yōu)點(diǎn):

1. 只需使用Lottie解析json文件就能實(shí)現(xiàn)動(dòng)畫(huà)的加載,基本上實(shí)現(xiàn)了0代碼開(kāi)發(fā);

2. 應(yīng)用開(kāi)發(fā)者可以通過(guò)修改json文件的參數(shù),將動(dòng)畫(huà)運(yùn)行到不同的應(yīng)用程序中,實(shí)現(xiàn)動(dòng)畫(huà)的一次設(shè)計(jì)多端使用;

3. 應(yīng)用開(kāi)發(fā)者可從網(wǎng)絡(luò)如https://lottiefiles.com/直接下載json文件,實(shí)時(shí)更新動(dòng)畫(huà)資源;

4. Lottie基于canvas畫(huà)布進(jìn)行基礎(chǔ)的2D渲染,讓動(dòng)畫(huà)流暢度更高;

5. Lottie可以將UX設(shè)計(jì)師給出的復(fù)雜動(dòng)畫(huà)效果100%還原到應(yīng)用程序中 ;

6. Lottie提供了豐富的API,讓開(kāi)發(fā)者能輕松控制動(dòng)畫(huà),大大提高了開(kāi)發(fā)效率。

如何使用Lottie?

1.導(dǎo)入Lottie

在Terminal窗口使用npm install @ohos/lottieETS命令下載Lottie,并在頁(yè)面中導(dǎo)入@ohos/lottieETS,如下:

importlottiefrom'@ohos/lottieETS'

放置動(dòng)畫(huà)資源

將After Effects導(dǎo)出的json動(dòng)畫(huà)資源文件保存到項(xiàng)目common/lottie路徑中,具體路徑如下:entry/src/main/ets/MainAbility/common/lottie/animation.json

69910728-3f2f-11ed-9e49-dac502259ad0.png

2. 創(chuàng)建Lottie動(dòng)畫(huà)

Lottie基于canvas畫(huà)布進(jìn)行基礎(chǔ)的2D渲染,創(chuàng)建canvas畫(huà)布后設(shè)置相關(guān)播放參數(shù)即可創(chuàng)建并播放Lottie動(dòng)畫(huà),Lottie更多信息可參考Lottie接口。

創(chuàng)建canvas畫(huà)布:

    @Builder TargetArea(controller:CanvasRenderingContext2D,lottieName:string) {        Stack() {            Canvas(controller)                .aspectRatio(1)                .width(300)                .offset({ y:  this.targetOffsetY })                .onAppear(() => {
                })            Animator('__lottie_ets') // declare Animator('__lottie_ets') when use lottie        }.height('100%').width(220)}
設(shè)置Lottie動(dòng)畫(huà)參數(shù):

    setLottie(controller:CanvasRenderingContext2D,lottieName:string,animatePath:string){        lottie.loadAnimation({            container: controller,            renderer: 'canvas',            loop: false,            autoplay: false,            name: lottieName,            path: animatePath,        })        lottie.setSpeed(1,lottieName)}
在“下落”動(dòng)畫(huà)擊拳監(jiān)聽(tīng)中加入播放不同效果的Lottie動(dòng)畫(huà)邏輯:

    judgeLeft(){       ......        if(nowTime > firstTime - 200 && nowTime < endTime){           ......            // 完美擊中            if (judgeTime/4 < handleTime && handleTime  < (judgeTime *(3/4))) {                lottie.destroy('animate_left')                this.setLottie(this.controllerLeft,'animate_left',this.animatePerfectPath)                lottie.play('animate_left') // 播放完美擊中動(dòng)畫(huà)                // 等動(dòng)畫(huà)執(zhí)行完成后才能進(jìn)入下一次揮拳判定                this.leftAnimateLock = true                setTimeout(()=>{                    lottie.stop()                    lottie.destroy('animate_left')                    this.leftAnimateLock = false                },this.lottieDuration)            }else if(handleTime < judgeTime){                // 擊中                lottie.destroy('animate_left')                this.setLottie(this.controllerLeft,'animate_left',this.animateJustPath)                lottie.play('animate_left')// 播放擊中動(dòng)畫(huà)                this.leftAnimateLock = true                setTimeout(()=>{                    lottie.stop()                    lottie.destroy('animate_left')                    this.leftAnimateLock = false                },this.lottieDuration)            }        }}

五、總結(jié)

本文主要講述了拳擊互動(dòng)游戲中,如何使用屬性動(dòng)畫(huà)實(shí)現(xiàn)簡(jiǎn)單屬性變化的動(dòng)畫(huà)效果,如游戲中“擊拳方塊”自上往下移動(dòng);使用Lottie組件實(shí)現(xiàn)復(fù)雜絢麗的動(dòng)畫(huà)效果,如游戲中的擊拳效果。

本樣例是OpenHarmony知識(shí)體系工作組(相關(guān)鏈接在文章末尾)為廣大開(kāi)發(fā)者分享的樣例。知識(shí)體系工作組結(jié)合日常生活,給開(kāi)發(fā)者規(guī)劃了各種場(chǎng)景的Demo樣例,如智能家居場(chǎng)景、影音娛樂(lè)場(chǎng)景、運(yùn)動(dòng)健康場(chǎng)景等。歡迎廣大開(kāi)發(fā)者一同參與OpenHarmony的開(kāi)發(fā),更加完善樣例,相互學(xué)習(xí),相互進(jìn)步。

審核編輯:彭靜
聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 定時(shí)器
    +關(guān)注

    關(guān)注

    23

    文章

    3248

    瀏覽量

    114792
  • 動(dòng)畫(huà)
    +關(guān)注

    關(guān)注

    0

    文章

    20

    瀏覽量

    8513
  • OpenHarmony
    +關(guān)注

    關(guān)注

    25

    文章

    3722

    瀏覽量

    16313

原文標(biāo)題:OpenHarmony有氧拳擊之應(yīng)用端開(kāi)發(fā)

文章出處:【微信號(hào):gh_e4f28cfa3159,微信公眾號(hào):OpenAtom OpenHarmony】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    HarmonyOS開(kāi)發(fā)案例:【動(dòng)效】

    利用ArkUI組件不僅可以實(shí)現(xiàn)局部屬性變化產(chǎn)生的屬性動(dòng)畫(huà),也可以實(shí)現(xiàn)父組件屬性
    的頭像 發(fā)表于 04-29 22:10 ?2321次閱讀
    HarmonyOS開(kāi)發(fā)案例:【動(dòng)效】

    LabVIEW中動(dòng)畫(huà)實(shí)現(xiàn)的一種新方法

    期更新控件的“Position”屬性實(shí)現(xiàn);合理編輯刀具控件Ture和False狀態(tài)的圖形,再將控件狀態(tài)作周期交替變化,可實(shí)現(xiàn)刀具轉(zhuǎn)動(dòng)效果
    發(fā)表于 01-08 11:30

    Scratch實(shí)現(xiàn)一個(gè)按鈕的動(dòng)畫(huà)效果

    上次介紹了利用克隆體操作生成菜單按鈕,今天講一講如何讓一個(gè)按鈕具有動(dòng)畫(huà)效果:當(dāng)鼠標(biāo)移到某個(gè)按鈕上面時(shí),顯示動(dòng)畫(huà)效果讓菜單按鈕有虛像效果讓菜
    發(fā)表于 06-29 08:51

    HarmonyOS Lottie組件,讓動(dòng)畫(huà)繪制更簡(jiǎn)單

    能力幫助開(kāi)發(fā)者美化了UI界面,但不適用于繪制某些比較復(fù)雜的動(dòng)畫(huà),例如,屬性動(dòng)畫(huà)主要針對(duì)動(dòng)畫(huà)的通用屬性進(jìn)行動(dòng)態(tài)
    發(fā)表于 02-22 14:55

    基于HarmonyOS實(shí)現(xiàn)的電池充電動(dòng)畫(huà)效果

    ;/option&gt;&lt;/select&gt;最終的效果總結(jié)這些還只是鴻蒙組件庫(kù)中動(dòng)畫(huà)樣式里的一小部分,如果再使用旋轉(zhuǎn)加平移屬性就能實(shí)現(xiàn)更加炫酷的
    發(fā)表于 03-28 12:02

    OpenHarmony有氧拳擊之應(yīng)用端開(kāi)發(fā)

    ; }五、總結(jié)本文主要講述了拳擊互動(dòng)游戲中,如何使用屬性動(dòng)畫(huà)實(shí)現(xiàn)簡(jiǎn)單屬性變化
    發(fā)表于 10-09 15:19

    如何使用lvgl定時(shí)器實(shí)現(xiàn)動(dòng)畫(huà)效果

    在LVGL中,如何使用lvgl定時(shí)器實(shí)現(xiàn)動(dòng)畫(huà)效果
    發(fā)表于 12-15 15:23

    HarmonyOS/OpenHarmony應(yīng)用開(kāi)發(fā)-屬性動(dòng)畫(huà)

    組件的某些通用屬性變化時(shí),可以通過(guò)屬性動(dòng)畫(huà)實(shí)現(xiàn)漸變過(guò)渡效果,提升用戶(hù)體驗(yàn)。支持的
    發(fā)表于 01-03 10:51

    HarmonyOS屬性動(dòng)畫(huà)開(kāi)發(fā)示例(ArkTS)

    介紹 利用 ArkUI 組件不僅可以實(shí)現(xiàn)屬性變化引起的屬性動(dòng)畫(huà),也可以實(shí)現(xiàn)父組件狀態(tài)
    發(fā)表于 11-23 15:31

    QML中的動(dòng)畫(huà)設(shè)計(jì),太“難”了

    alwaysRunToEnd:該屬性接收布爾類(lèi)型的參數(shù)。該屬性保存動(dòng)畫(huà)是否運(yùn)行到完成才停止。當(dāng)loops屬性被設(shè)置時(shí),這個(gè)屬性是最有用的,因
    的頭像 發(fā)表于 09-09 10:16 ?1596次閱讀

    在QML動(dòng)畫(huà)設(shè)計(jì)中通過(guò)指定關(guān)鍵幀創(chuàng)建時(shí)間線動(dòng)畫(huà)

    在QML動(dòng)畫(huà)設(shè)計(jì)中,可以通過(guò)指定關(guān)鍵幀創(chuàng)建時(shí)間線動(dòng)畫(huà);還可以將時(shí)間線綁定到組件(如滑塊)的屬性值,以這種方式控制動(dòng)畫(huà)。
    的頭像 發(fā)表于 10-10 11:27 ?2144次閱讀

    鴻蒙開(kāi)發(fā)之發(fā)動(dòng)畫(huà)

    FPS(Frame Per Second),即每秒的動(dòng)畫(huà)幀數(shù),幀率越高則動(dòng)畫(huà)就會(huì)越流暢。 ArkUI中,產(chǎn)生動(dòng)畫(huà)的方式是改變屬性值且指定動(dòng)畫(huà)
    的頭像 發(fā)表于 02-01 15:25 ?633次閱讀
    鴻蒙開(kāi)發(fā)之發(fā)<b class='flag-5'>動(dòng)畫(huà)</b>篇

    HarmonyOS開(kāi)發(fā)案例:【動(dòng)畫(huà)

    使用動(dòng)畫(huà)樣式,實(shí)現(xiàn)幾種常見(jiàn)動(dòng)畫(huà)效果:平移、旋轉(zhuǎn)、縮放以及透明度變化
    的頭像 發(fā)表于 04-25 15:13 ?473次閱讀
    HarmonyOS開(kāi)發(fā)案例:【<b class='flag-5'>動(dòng)畫(huà)</b>】

    OpenHarmony實(shí)戰(zhàn)開(kāi)發(fā)-如何實(shí)現(xiàn)組件動(dòng)畫(huà)。

    ArkUI為組件提供了通用的屬性動(dòng)畫(huà)和轉(zhuǎn)場(chǎng)動(dòng)畫(huà)能力的同時(shí),還為一些組件提供了默認(rèn)的動(dòng)畫(huà)效果。例如,List的滑動(dòng)動(dòng)效,Button的點(diǎn)擊動(dòng)效
    的頭像 發(fā)表于 04-28 15:49 ?630次閱讀
    OpenHarmony實(shí)戰(zhàn)開(kāi)發(fā)-如何<b class='flag-5'>實(shí)現(xiàn)</b>組件<b class='flag-5'>動(dòng)畫(huà)</b>。

    HarmonyOS開(kāi)發(fā)案例:【自定義下拉刷新動(dòng)畫(huà)

    主要介紹組件動(dòng)畫(huà)animation屬性設(shè)置。當(dāng)組件的某些通用屬性變化時(shí),可以通過(guò)屬性動(dòng)畫(huà)
    的頭像 發(fā)表于 04-29 16:06 ?966次閱讀
    HarmonyOS開(kāi)發(fā)案例:【自定義下拉刷新<b class='flag-5'>動(dòng)畫(huà)</b>】