ArkUI轉(zhuǎn)場(chǎng)動(dòng)畫(huà)的使用—學(xué)習(xí)筆記
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
前言
好久不見(jiàn),甚是想念!最近學(xué)業(yè)上有點(diǎn)小忙,擱置了一個(gè)半月,但我又回來(lái)啦!好好學(xué)習(xí),天天向上(ง •_•)ง
最近看了官方文檔上“轉(zhuǎn)場(chǎng)動(dòng)畫(huà)的使用(eTS)”的案例,也跟著學(xué)習(xí)了一下,順便做點(diǎn)筆記O(∩_∩)O
概述
效果圖如下:





正文
一.新建項(xiàng)目
DevEco Studio下載安裝成功后,打開(kāi)DevEco Studio,點(diǎn)擊左上角的File,點(diǎn)擊New,再選擇New Project,選擇Empty Ability,然后點(diǎn)擊Next,給項(xiàng)目命名Animation,選擇設(shè)備類型Phone,選擇語(yǔ)言類型ets,API Version選擇7,最后點(diǎn)擊Finish
初始目錄的各個(gè)文件夾和文件的作用:
index.ets:用于描述UI布局、樣式、事件交互和頁(yè)面邏輯。
app.ets:用于全局應(yīng)用邏輯和應(yīng)用生命周期管理。
pages:用于存放所有組件頁(yè)面。
java:用于存放Ability等Java代碼。
resources:用于存放資源配置文件,比如:國(guó)際化字符串、資源限定相關(guān)資源和rawfile資源等。
二.構(gòu)建主界面
從上面效果圖可以看出,主界面主要由5個(gè)相同樣式的功能菜單組成,我們可以將這些菜單抽取成一個(gè)子組件Item。
1.添加圖片
將所需要的圖片添加到resources > rawfile目錄下。

2.新建子組件
在index.ets中新建名為Item的子組件,聲明子組件Item的UI布局并添加樣式。創(chuàng)建Stack組件,包含圖片和文本,然后添加文本信息和頁(yè)面跳轉(zhuǎn)事件,定義變量text和uri。其中text用于給Text組件設(shè)置文本信息,uri用于設(shè)置頁(yè)面路由的地址。代碼如下:
- @Component
- struct Item {
- private text: string
- private uri: string
- build() {
- Stack({ alignContent: Alignment.Center }) {
- Image($rawfile('image1.jfif'))
- .objectFit(ImageFit.Cover)
- .width('100%')
- .height(100)
- .borderRadius(15)
- Text(this.text)
- .fontSize(20)
- .fontWeight(FontWeight.Bold)
- .fontColor(Color.Black)
- }
- .onClick(() => {
- router.push({ uri: this.uri })
- })
- .height(100)
- .borderRadius(15)
- .width('80%')
- .margin({ bottom: 20 })
- }
- }
3.將子組件添加到Index組件中
將Item組件添加到Index組件中,并給Item傳入?yún)?shù)text和uri,由于還未創(chuàng)建要跳轉(zhuǎn)的頁(yè)面,所以這里uri暫時(shí)傳空字符串。
- @Entry
- @Component
- struct Index {
- build() {
- Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
- Item({ text: '頁(yè)面間轉(zhuǎn)場(chǎng):底部滑入', uri: '' })
- Item({ text: '頁(yè)面間轉(zhuǎn)場(chǎng):自定義1', uri: '' })
- Item({ text: '頁(yè)面間轉(zhuǎn)場(chǎng):自定義2', uri: '' })
- Item({ text: '組件內(nèi)轉(zhuǎn)場(chǎng)', uri: '' })
- Item({ text: '共享元素轉(zhuǎn)場(chǎng)', uri: '' })
- }
- .width('100%')
- .height('100%')
- .backgroundColor('#FFECECEC')
- }
- }
三.實(shí)現(xiàn)頁(yè)面間轉(zhuǎn)場(chǎng)
1.文件架構(gòu)
在pages目錄下新建名為page的package,然后在page目錄下,點(diǎn)擊鼠標(biāo)右鍵分別新建名為BottomTransition、CustomTransition和FullCustomTransition的三個(gè)ets文件。其中BottomTransition用于實(shí)現(xiàn)"頁(yè)面間轉(zhuǎn)場(chǎng):底部滑入"動(dòng)效;CustomTransition用于實(shí)現(xiàn)"頁(yè)面間轉(zhuǎn)場(chǎng):自定義1"動(dòng)效;FullCustomTransition用于實(shí)現(xiàn)"頁(yè)面間轉(zhuǎn)場(chǎng):自定義2"動(dòng)效。
新建后,打開(kāi)config.json文件會(huì)看到pages標(biāo)簽下自動(dòng)添加了BottomTransition、CustomTransition和FullCustomTransition的路由地址,如果沒(méi)有的話就自己手動(dòng)添加。

tips: 1.頁(yè)面文件名不能使用組件名稱,比如:Text.ets、Button.ets等。2.每個(gè)頁(yè)面文件中必須包含入口組件。3.pages列表中第一個(gè)頁(yè)面為應(yīng)用的首頁(yè)入口。
2.實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)
在主界面index.ets的Index組件中,將BottomTransition、CustomTransition和FullCustomTransition的路由地址賦值給對(duì)應(yīng)Item的uri。
- import router from '@system.router';
- @Entry
- @Component
- struct Index {
- build() {
- Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
- Item({ text: '頁(yè)面間轉(zhuǎn)場(chǎng):底部滑入', uri: 'pages/page/BottomTransition' })
- Item({ text: '頁(yè)面間轉(zhuǎn)場(chǎng):自定義1', uri: 'pages/page/CustomTransition' })
- Item({ text: '頁(yè)面間轉(zhuǎn)場(chǎng):自定義2', uri: 'pages/page/FullCustomTransition' })
- Item({ text: '組件內(nèi)轉(zhuǎn)場(chǎng)', uri: '' })
- Item({ text: '共享元素轉(zhuǎn)場(chǎng)', uri: '' })
- }
- .width('100%')
- .height('100%')
- .backgroundColor('#FFECECEC')
- }
- }
3.實(shí)現(xiàn)"底部滑入"動(dòng)效
在BottomTransition申明pageTransition方法配置轉(zhuǎn)場(chǎng)參數(shù),其中PageTransitionEnter用于自定義當(dāng)前頁(yè)面的入場(chǎng)效果,PageTransitionExit用于自定義當(dāng)前頁(yè)面的退場(chǎng)效果。在這里我們?cè)O(shè)置PageTransitionEnter和PageTransitionExit的slide屬性為SlideEffect.Bottom,來(lái)實(shí)現(xiàn)BottomTransition入場(chǎng)時(shí)從底部滑入,退場(chǎng)時(shí)從底部滑出。
- @Entry
- @Component
- struct BottomTransition{
- build() {
- Stack() {
- Image($rawfile('image2.jfif'))
- .objectFit(ImageFit.Cover)
- .width('100%')
- .height('100%')
- }
- .width('100%')
- .height('100%')
- }
- pageTransition() {
- PageTransitionEnter({ duration: 600, curve: Curve.Smooth })
- .slide(SlideEffect.Bottom)
- PageTransitionExit({ duration: 600, curve: Curve.Smooth })
- .slide(SlideEffect.Bottom)
- }
- }
效果如下:

4.實(shí)現(xiàn)"頁(yè)面轉(zhuǎn)場(chǎng):自定義1"動(dòng)效
在CustomTransition.ets的CustomTransition組件中添加Stack組件和Image組件,并且定義pageTransition方法。我實(shí)現(xiàn)的效果是進(jìn)場(chǎng)淡入退場(chǎng)淡出。代碼如下:
- @Entry
- @Component
- struct CustomTransition{
- build() {
- Stack() {
- Image($rawfile('image3.jfif'))
- .objectFit(ImageFit.Cover)
- .width('100%')
- .height('100%')
- }
- .width('100%')
- .height('100%')
- }
- pageTransition() {
- PageTransitionEnter({ duration: 1500, curve: Curve.Smooth })
- .opacity(0.2)
- PageTransitionExit({ duration:1000, curve: Curve.Smooth })
- .opacity(0)
- }
- }
效果如下:

5.實(shí)現(xiàn)"頁(yè)面轉(zhuǎn)場(chǎng):自定義2"動(dòng)效
實(shí)現(xiàn)的效果:頁(yè)面入場(chǎng)時(shí)淡入和放大,同時(shí)順時(shí)針旋轉(zhuǎn);退場(chǎng)時(shí)淡出和縮小,同時(shí)逆時(shí)針旋轉(zhuǎn)。
在FullCustomTransition.ets的FullCustomTransition組件中添加Stack組件和Image組件,并且定義pageTransition方法。給Stack組件添加opacity、scale、rotate屬性,定義變量myProgress用來(lái)控制Stack組件的動(dòng)效,在PageTransitionEnter和PageTransitionExit組件中動(dòng)態(tài)改變myProgress的值。代碼如下:
- @Entry
- @Component
- struct FullCustomTransition{
- @State myProgress: number = 1
- build() {
- Stack() {
- Image($rawfile('image2.jfif'))
- .objectFit(ImageFit.Cover)
- .width('100%')
- .height('100%')
- }
- .width('100%')
- .height('100%')
- .opacity(this.myProgress)
- .scale({ x: this.myProgress, y: this.myProgress })
- .rotate({ x: 0, y: 0, z: 1, angle: 360 * this.myProgress })
- }
- pageTransition() {
- PageTransitionEnter({ duration: 1000, curve: Curve.Smooth })
- .onEnter((type: RouteType, progress: number) => {
- this.myProgress = progress
- })
- PageTransitionExit({ duration: 1000, curve: Curve.Smooth })
- .onExit((type: RouteType, progress: number) => {
- this.myProgress = 1 - progress
- })
- }
- }
效果如下:

四.實(shí)現(xiàn)組件內(nèi)轉(zhuǎn)場(chǎng)
實(shí)現(xiàn)組件內(nèi)轉(zhuǎn)場(chǎng)動(dòng)效,通過(guò)一個(gè)按鈕來(lái)控制組件的添加和移除,呈現(xiàn)容器組件子組件添加和移除時(shí)的動(dòng)效。組件轉(zhuǎn)場(chǎng)主要通過(guò)transition屬性方法配置轉(zhuǎn)場(chǎng)參數(shù),在組件添加和移除時(shí)會(huì)執(zhí)行過(guò)渡動(dòng)效,需要配合animteTo才能生效。動(dòng)效時(shí)長(zhǎng)、曲線、延時(shí)跟隨animateTo中的配置。
1.新建文件
在pages目錄下,新建名為ComponentTransition的ets文件
2.新建子組件
在ComponentTransition.ets文件中,新建ComponentItem子組件,添加Stack組件和Image組件。給Stack添加兩個(gè)transition屬性,分別用于定義組件的添加動(dòng)效和移除動(dòng)效。
- @Component
- struct ComponentItem {
- build() {
- Stack({ alignContent: Alignment.Center }) {
- Image($rawfile('image1.jfif'))
- .objectFit(ImageFit.Cover)
- .width('100%')
- .height(120)
- .borderRadius(15)
- }
- .height(120)
- .borderRadius(15)
- .width('80%')
- .margin({ top: 20 })
- .transition({ type: TransitionType.Insert, scale: { x: 0.5, y: 0.5 }, opacity: 0 })
- .transition({ type: TransitionType.Delete, rotate: { x: 0, y: 1, z: 0, angle: 360 }, scale: { x: 0, y: 0 } })
- }
- }
3.添加子組件
在ComponentTransition組件定義一個(gè)變量,用于控制ComponentItem的添加和移除,在Button組件的onClick事件中添加animateTo方法,來(lái)使ComponentItem子組件動(dòng)效生效。
- @Entry
- @Component
- struct ComponentTransition {
- @State private isShow: boolean= false
- build() {
- Column() {
- if (this.isShow) {
- ComponentItem()
- }
- ComponentItem()
- Button("Toggle")
- .onClick(() => {
- animateTo({ duration: 600 }, () => {
- this.isShow = !this.isShow;
- })
- })
- .height(45)
- .width(200)
- .fontColor(Color.Black)
- .backgroundColor('rgb(203,155,192)')
- .margin({ top: 20 })
- }
- .padding({ left: 20, right: 20 })
- .backgroundColor('#FFECECEC')
- .height('100%')
- .width('100%')
- }
- }
效果圖如下:

五.實(shí)現(xiàn)元素共享轉(zhuǎn)場(chǎng)
共享元素轉(zhuǎn)場(chǎng)通過(guò)給組件設(shè)置sharedTransition屬性來(lái)實(shí)現(xiàn),兩個(gè)頁(yè)面的組件配置為同一個(gè)id,則轉(zhuǎn)場(chǎng)過(guò)程中會(huì)執(zhí)行共享元素轉(zhuǎn)場(chǎng)。sharedTransition可以設(shè)置動(dòng)效的時(shí)長(zhǎng)、動(dòng)畫(huà)曲線和延時(shí)。
1.首先在pages目錄下新建名為share的包,然后在share目錄下分別新建名為ShareItem和SharePage的ets文件。其中ShareItem.ets用于展示小圖,SharePage.ets用于展示大圖。

2.在ShareItem.ets中給Image組件設(shè)置sharedTransition屬性,組件轉(zhuǎn)場(chǎng)id設(shè)置為"imageId"。
- import router from '@system.router'
- @Entry
- @Component
- struct ShareItem{
- build() {
- Flex() {
- Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
- Stack() {
- Image($rawfile('image3.jfif'))
- // 設(shè)置共享元素轉(zhuǎn)場(chǎng)屬性
- .sharedTransition('imageId', { duration: 600, curve: Curve.Smooth, delay: 100 })
- .onClick(() => {
- router.push({ uri: 'pages/share/SharePage' })
- })
- .objectFit(ImageFit.Cover)
- .height('100%')
- .width('100%')
- .borderRadius(15)
- }
- .height('100%')
- .width('100%')
- Text('點(diǎn)擊查看共享元素轉(zhuǎn)場(chǎng)動(dòng)效')
- .fontSize(20)
- .fontColor(Color.Black)
- .fontWeight(FontWeight.Regular)
- .margin({ left: 10, right: 10 })
- }
- .height(120)
- .backgroundColor('rgb(181,222,224)')
- .borderRadius(15)
- .margin({ top: 20 })
- }
- .width('100%')
- .padding({ left: 16, right: 16 })
- .backgroundColor('#FFECECEC')
- }
- }
3.在SharePage.ets中給Image組件設(shè)置sharedTransition屬性,組件轉(zhuǎn)場(chǎng)id設(shè)置為"imageId"。
- @Entry
- @Component
- struct SharePage{
- build() {
- Stack() {
- Image($rawfile('image3.jfif'))
- // 設(shè)置共享元素轉(zhuǎn)場(chǎng)屬性
- .sharedTransition('imageId', { duration: 1000, curve: Curve.Smooth, delay: 100 })
- .objectFit(ImageFit.Cover)
- .width('100%')
- .height('100%')
- }
- .width('100%')
- .height('100%')
- }
- }
4.最后別忘在主界面添加相應(yīng)路由地址。
- import router from '@system.router';
- @Entry
- @Component
- struct Index {
- build() {
- Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
- Item({ text: '頁(yè)面間轉(zhuǎn)場(chǎng):底部滑入', uri: 'pages/page/BottomTransition' })
- Item({ text: '頁(yè)面間轉(zhuǎn)場(chǎng):自定義1', uri: 'pages/page/CustomTransition' })
- Item({ text: '頁(yè)面間轉(zhuǎn)場(chǎng):自定義2', uri: 'pages/page/FullCustomTransition' })
- Item({ text: '組件內(nèi)轉(zhuǎn)場(chǎng)', uri: 'pages/ComponentTransition' })
- Item({ text: '共享元素轉(zhuǎn)場(chǎng)', uri: 'pages/share/ShareItem' })
- }
- .width('100%')
- .height('100%')
- .backgroundColor('#FFECECEC')
- }
- }
效果圖如下:

tips:1.兩個(gè)頁(yè)面的組件配置為同一個(gè)id,則轉(zhuǎn)場(chǎng)過(guò)程中會(huì)執(zhí)行共享元素轉(zhuǎn)場(chǎng),配置為空字符串時(shí)不會(huì)有共享元素轉(zhuǎn)場(chǎng)效果。
2.在 config.json文件里在 “launchType”: "standard"后面添加以下代碼就能去掉左上角的標(biāo)簽欄。
- "icon": "$media:icon",
- "description": "$string:mainability_description",
- "label": "$string:entry_MainAbility",
- "type": "page",
- "launchType": "standard",
- "metaData": {
- "customizeData": [
- {
- "name": "hwc-theme",
- "value": "androidhwext:style/Theme.Emui.Light.NoTitleBar",
- "extra": ""
- }
- ]
- }
結(jié)語(yǔ)
以上就是我這次的小分享啦❀❀!
文章相關(guān)附件可以點(diǎn)擊下面的原文鏈接前往下載
https://harmonyos.51cto.com/resource/1600
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):