想了解更多關于開源的內容,請訪問:
51CTO 開源基礎軟件社區
https://ost.51cto.com
在日常應用場景中,水波紋的效果比較常見,例如數字鍵盤按鍵效果、聽歌識曲、附近搜索雷達動效等等,本文就以數字按鍵為例介紹水波紋動效的實現。
本例最終效果圖如下:
本例基于以下環境開發,開發者也可以基于其他適配的版本進行開發:
本實例涉及到的主要特性及其實現方案如下:
針對實現思路中所提到的內容,具體關鍵開發步驟如下:
先通過Grid,GridItem等容器組件將UI框架搭建起來,在GuidItem中引用步驟2中的自定義數字按鈕numBtn構建出數字柵格。
具體代碼如下:
private numGrid: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, -1, 0, -1] ... Column() { Grid() { ForEach(this.numGrid, (item: number, index: number) => { GridItem() { ... } }, item => item) } .columnsTemplate('1fr 1fr 1fr') .rowsTemplate('1fr 1fr 1fr 1fr') .columnsGap(10) .rowsGap(10) .width(330) .height(440) }.width('100%').height('100%')
通過Column、Button、Stack、Text等關鍵組件以及visibility屬性構建自定義數字按鈕numBtn。
具體代碼如下:
@Componentstruct numBtn { ··· build() { Column() { Button() { stack(){ ... Text(`${this.item}`).fontSize(30) } ... } .backgroundColor('#ccc') .type(ButtonType.Circle) .borderRadius(100) .width(100) .height(100) } .visibility(this.item == -1 ? Visibility.Hidden : Visibility.Visible) .borderRadius(100) }}
設置狀態變量unPressed,監聽當前數字按鈕的狀態,同時向Column組件添加onTouch事件,獲取并更新按鈕的當前狀態,從而可以根據監聽到的按鈕狀態加載對應的動畫效果。
具體代碼塊如下:
//狀態變量unPressed,用于監聽按鈕按下和放開的狀態@State unPressed: boolean = true ...// 添加onTouch事件,監聽狀態.onTouch((event: TouchEvent) => { // 當按鈕按下時,更新按鈕的狀態(unPressed:true -> false) if (event.type == TouchType.Down) { animateTo({ duration: 400 }, () => { this.unPressed = !this.unPressed this.currIndex = this.index }) } // 當按鈕放開時,更新按鈕的狀態(unPressed:false -> true) if (event.type == TouchType.Up) { animateTo({ duration: 400 }, () => { this.unPressed = !this.unPressed }) }})
根據按鈕組件的按下/放開狀態,通過if-else語句選擇插入的Row組件,并隨之呈現不同的水波動畫效果(按下時水波聚攏,放開時水波擴散)。
具體代碼塊如下:
Stack() { Row() { // 判斷當前按鈕組件為放開狀態 if (this.unPressed && this.currIndex == this.index) { // 插入Row組件,配置過渡效果 Row() .customStyle() .backgroundColor('#fff') // 水波紋擴散動畫:從Row組件的中心點開始放大,scale{0,0}變更scale{1,1}(完整顯示) .transition({ type: TransitionType.Insert, opacity: 0, scale: { x: 0, y: 0, centerY: '50%', centerX: '50%' } }) } // 判斷當前按鈕組件為按下狀態 else if (!this.unPressed && this.currIndex == this.index) { // 插入Row組件,配置過渡效果 Row() .customStyle() .backgroundColor(this.btnColor) .scale(this.btnScale) .onAppear(() => { // 水波紋聚攏動畫:Row組件backgroundColor屬性變更(#ccc -> #fff),插入動畫過渡效果,scale{1,1}(完整顯示)變化為scale{0,0} animateTo({ duration: 300, // 聚攏動畫播放完成后,需要銜接擴散動畫,Row組件backgroundColor屬性變更(#fff -> #ccc),插入動畫過渡效果,scale{0,0}變化為scale{1,1}(完整顯示) onFinish: () => { this.btnColor = '#ccc' this.btnScale = { x: 1, y: 1 } } }, () => { this.btnColor = '#fff' this.btnScale = { x: 0, y: 0 } }) }) } // 其他狀態 else { Row() .customStyle() .backgroundColor('#fff') } } .justifyContent(FlexAlign.Center) .alignItems(VerticalAlign.Center) .borderRadius(100) Text(`${this.item}`).fontSize(30)}.customStyle()
示例代碼如下:
@Entry@Componentexport default struct dragFire { private numGrid: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, -1, 0, -1] build() { Column() { Grid() { ForEach(this.numGrid, (item: number, index: number) => { GridItem() { numBtn({ item: item, index: index }) } }, item => item) } .columnsTemplate('1fr 1fr 1fr') .rowsTemplate('1fr 1fr 1fr 1fr') .columnsGap(10) .rowsGap(10) .width(330) .height(440) }.width('100%').height('100%') }}@Componentstruct numBtn { private currIndex: number = -1 //狀態變量unPressed,用于控制按鈕的狀態 @State unPressed: boolean = true @State btnColor: string = '#ccc' index: number item: number @State btnScale: { x: number, y: number } = { x: 1, y: 1 } @Styles customStyle(){ .width('100%') .height('100%') .borderRadius(100) } build() { Column() { Button() { Stack() { Row() { // 判斷當前組件為放開狀態 if (this.unPressed && this.currIndex == this.index) { // 插入Row組件,配置過渡效果 Row() .customStyle() .backgroundColor('#fff') // 水波紋擴散動畫:Row組件backgroundColor屬性變更(#fff -> #ccc),系統插入動畫過渡效果,從組建的中心點開始放大,scale{0,0}變更scale{1,1} .transition({ type: TransitionType.Insert, opacity: 0, scale: { x: 0, y: 0, centerY: '50%', centerX: '50%' } }) } // 判斷當前組件為按下狀態 else if (!this.unPressed && this.currIndex == this.index) { // 插入Row組件,配置過渡效果 Row() .customStyle() .backgroundColor(this.btnColor) .scale(this.btnScale) .onAppear(() => { // 水波紋聚攏動畫:Row組件backgroundColor屬性變更(#ccc -> #fff),插入動畫過渡效果,scale{1,1}變化為scale{0,0} animateTo({ duration: 300, // 聚攏動畫播放完成后,需要銜接擴散動畫,此時Row組件backgroundColor屬性變更(#fff -> #ccc),插入動畫過渡效果,scale{0,0}變化為scale{1,1} onFinish: () => { this.btnColor = '#ccc' this.btnScale = { x: 1, y: 1 } } }, () => { this.btnColor = '#fff' this.btnScale = { x: 0, y: 0 } }) }) } // 其他狀態 else { Row() .customStyle() .backgroundColor('#fff') } } .justifyContent(FlexAlign.Center) .alignItems(VerticalAlign.Center) .borderRadius(100) Text(`${this.item}`).fontSize(30) } .customStyle() } .stateEffect(false) .backgroundColor('#ccc') .type(ButtonType.Circle) .borderRadius(100) .width(100) .height(100) } .visibility(this.item == -1 ? Visibility.Hidden : Visibility.Visible) .borderRadius(100) // onTouch事件,監聽狀態 .onTouch((event: TouchEvent) => { // 當按鈕按下時,更新按鈕的狀態(unPressed:true -> false) if (event.type == TouchType.Down) { animateTo({ duration: 400 }, () => { this.unPressed = !this.unPressed this.currIndex = this.index }) } // 當按鈕放開時,更新按鈕的狀態(unPressed:false -> true) if (event.type == TouchType.Up) { animateTo({ duration: 400 }, () => { this.unPressed = !this.unPressed }) } }) }}
想了解更多關于開源的內容,請訪問:
51CTO 開源基礎軟件社區
https://ost.51cto.com
本文鏈接:http://www.www897cc.com/showinfo-26-50743-0.html水波紋動畫開發(ArkUI)
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com