介紹
在本教程中,我們將會(huì)通過(guò)一個(gè)簡(jiǎn)單的樣例,學(xué)習(xí)如何基于ArkTS的聲明式開(kāi)發(fā)范式開(kāi)發(fā)轉(zhuǎn)場(chǎng)動(dòng)畫。其中包含頁(yè)面間轉(zhuǎn)場(chǎng)、組件內(nèi)轉(zhuǎn)場(chǎng)以及共享元素轉(zhuǎn)場(chǎng)。效果如圖所示:
說(shuō)明: 本Codelab使用的display接口處于mock階段,在預(yù)覽器上使用會(huì)顯示白屏現(xiàn)象,可選擇在真機(jī)或模擬器上運(yùn)行。
相關(guān)概念
- [頁(yè)面間轉(zhuǎn)場(chǎng)]:頁(yè)面轉(zhuǎn)場(chǎng)通過(guò)在全局pageTransition方法內(nèi)配置頁(yè)面入場(chǎng)組件和頁(yè)面退場(chǎng)組件來(lái)自定義頁(yè)面轉(zhuǎn)場(chǎng)動(dòng)效。
- [組件內(nèi)轉(zhuǎn)場(chǎng)]:組件轉(zhuǎn)場(chǎng)主要通過(guò)transition屬性進(jìn)行配置轉(zhuǎn)場(chǎng)參數(shù),在組件插入和刪除時(shí)進(jìn)行過(guò)渡動(dòng)效,主要用于容器組件子組件插入刪除時(shí)提升用戶體驗(yàn)(需要配合animateTo才能生效,動(dòng)效時(shí)長(zhǎng)、曲線、延時(shí)跟隨animateTo中的配置)。
- [共享元素轉(zhuǎn)場(chǎng)]:通過(guò)修改共享元素的sharedTransition屬性設(shè)置元素在不同頁(yè)面之間過(guò)渡動(dòng)效。例如,如果兩個(gè)頁(yè)面使用相同的圖片(但位置和大小不同),圖片就會(huì)在這兩個(gè)頁(yè)面之間流暢地平移和縮放。
環(huán)境搭建
軟件要求
- [DevEco Studio]版本:DevEco Studio 3.1 Release。
- OpenHarmony SDK版本:API version 9。
硬件要求
- 開(kāi)發(fā)板類型:[潤(rùn)和RK3568開(kāi)發(fā)板]。
- OpenHarmony系統(tǒng):3.2 Release。
環(huán)境搭建
完成本篇Codelab我們首先要完成開(kāi)發(fā)環(huán)境的搭建,本示例以RK3568開(kāi)發(fā)板為例,參照以下步驟進(jìn)行:
- [獲取OpenHarmony系統(tǒng)版本]:標(biāo)準(zhǔn)系統(tǒng)解決方案(二進(jìn)制)。以3.2 Release版本為例:
- 搭建燒錄環(huán)境。
- [完成DevEco Device Tool的安裝]
- [完成RK3568開(kāi)發(fā)板的燒錄](méi)
- 搭建開(kāi)發(fā)環(huán)境。
代碼結(jié)構(gòu)解讀
本篇Codelab只對(duì)核心代碼進(jìn)行講解,完整代碼可以直接從gitee獲取。
├──entry/src/main/ets // 代碼區(qū)
│ ├──common
│ │ ├──constants
│ │ │ └──CommonConstants.ets // 公共常量類
│ │ └──utils
│ │ ├──DimensionUtil.ets // 屏幕適配工具類
│ │ └──GlobalContext.ets // 全局上下文工具類
│ ├──entryability
│ │ └──EntryAbility.ets // 程序入口類
│ ├──pages
│ │ ├──BottomTransition.ets // 底部滑出頁(yè)面
│ │ ├──ComponentTransition.ets // 移動(dòng)動(dòng)畫轉(zhuǎn)場(chǎng)頁(yè)面
│ │ ├──CustomTransition.ets // 放縮動(dòng)畫轉(zhuǎn)場(chǎng)頁(yè)面
│ │ ├──FullCustomTransition.ets // 旋轉(zhuǎn)動(dòng)畫轉(zhuǎn)場(chǎng)頁(yè)面
│ │ ├──Index.ets // 應(yīng)用首頁(yè)
│ │ ├──ShareItem.ets // 共享元素轉(zhuǎn)場(chǎng)部件
│ │ └──SharePage.ets // 共享元素轉(zhuǎn)場(chǎng)頁(yè)面
│ ├──view
│ │ ├──BackContainer.ets // 自定義頭部返回組件
│ │ └──TransitionElement.ets // 自定義動(dòng)畫元素
│ └──viewmodel
│ └──AnimationModel.ets // 動(dòng)畫封裝的model類
└──entry/src/main/resources // 資源文件目錄
`HarmonyOS與OpenHarmony鴻蒙文檔籽料:mau123789是v直接拿`
構(gòu)建主界面
在這個(gè)任務(wù)中,我們將完成主界面的設(shè)計(jì)和開(kāi)發(fā),效果如圖所示:
從上面效果圖可以看出,主界面主要由5個(gè)相同樣式的功能菜單組成,我們可以將這些菜單抽取成一個(gè)子組件Item。
- 將所需要的圖片添加到resources > base > media目錄下。
- 在Index.ets中引入首頁(yè)所需要圖片和路由信息,聲明子組件的UI布局并添加樣式,使用ForEach方法循環(huán)渲染首頁(yè)列表常量數(shù)據(jù)“INDEX_ANIMATION_MODE”,其中imgRes是設(shè)置按鈕的背景圖片,url用于設(shè)置頁(yè)面路由的地址。
// Index.ets import { INDEX_ANIMATION_MODE } from '../common/constants/CommonConstants'; Column() { ForEach(INDEX_ANIMATION_MODE, (item: AnimationModel) = > { Row() .backgroundImage(item.imgRes) .backgroundImageSize(ImageSize.Cover) .backgroundColor($r('app.color.trans_parent')) .height(DimensionUtil.getVp($r('app.float.main_page_body_height'))) .margin({ bottom: DimensionUtil.getVp($r('app.float.main_page_body_margin')) }) .width(FULL_LENGTH) .borderRadius(BORDER_RADIUS) .onClick(() = > { router.pushUrl({ url: item.url }) .catch((err: Error) = > { hilog.error(DOMAIN, PREFIX, FORMAT, err); }); }) }, (item: AnimationModel) = > JSON.stringify(item)) }
頁(yè)面間轉(zhuǎn)場(chǎng)
實(shí)現(xiàn)“底部滑入”效果
在BottomTransition申明pageTransition方法配置轉(zhuǎn)場(chǎng)參數(shù),其中PageTransitionEnter用于自定義當(dāng)前頁(yè)面的入場(chǎng)效果,PageTransitionExit用于自定義當(dāng)前頁(yè)面的退場(chǎng)效果。效果如圖所示:
通過(guò)設(shè)置PageTransitionEnter和PageTransitionExit的slide屬性為SlideEffect.Bottom,來(lái)實(shí)現(xiàn)BottomTransition入場(chǎng)時(shí)從底部滑入,退場(chǎng)時(shí)從底部滑出。
// BottomTransition.ets
@Entry
@Component
struct BottomTransition {
build() {
Column() {
TransitionElement()
}
}
/**
* 頁(yè)面轉(zhuǎn)場(chǎng)通過(guò)全局pageTransition方法進(jìn)行配置轉(zhuǎn)場(chǎng)參數(shù)
*
* SlideEffect.Bottom 入場(chǎng)時(shí)從屏幕下方滑入。
* SlideEffect.Bottom 退場(chǎng)時(shí)從屏幕下方滑出。
*/
pageTransition() {
PageTransitionEnter({ duration: TRANSITION_ANIMATION_DURATION, curve: Curve.Smooth }).slide(SlideEffect.Bottom);
PageTransitionExit({ duration: TRANSITION_ANIMATION_DURATION, curve: Curve.Smooth }).slide(SlideEffect.Bottom);
}
}
實(shí)現(xiàn)”頁(yè)面轉(zhuǎn)場(chǎng):自定義1“效果
本節(jié)實(shí)現(xiàn)的效果,頁(yè)面入場(chǎng)時(shí)為淡入和放大,退場(chǎng)時(shí)從右下角滑出。效果如圖所示:
在CustomTransition.ets的Column組件中添加TransitionElement組件,并且定義pageTransition方法。
// CustomTransition.ets
@Entry
@Component
struct CustomTransition {
build() {
Column() {
TransitionElement()
}
}
/**
* 頁(yè)面轉(zhuǎn)場(chǎng)通過(guò)全局pageTransition方法進(jìn)行配置轉(zhuǎn)場(chǎng)參數(shù)
*
* 進(jìn)場(chǎng)時(shí)透明度設(shè)置從0.2到1;x、y軸縮放從0變化到1
* 退場(chǎng)時(shí)x、y軸的偏移量為500
*/
pageTransition() {
PageTransitionEnter({ duration: TRANSITION_ANIMATION_DURATION, curve: Curve.Smooth })
.opacity(CUSTOM_TRANSITION_OPACITY)
.scale(CUSTOM_TRANSITION_SCALE)
PageTransitionExit({ duration: TRANSITION_ANIMATION_DURATION, curve: Curve.Smooth })
.translate(CUSTOM_TRANSITION_TRANSLATE)
}
}
說(shuō)明: translate設(shè)置頁(yè)面轉(zhuǎn)場(chǎng)時(shí)的平移效果,為入場(chǎng)時(shí)起點(diǎn)和退場(chǎng)時(shí)終點(diǎn)的值,和slide同時(shí)設(shè)置時(shí)默認(rèn)生效slide。
實(shí)現(xiàn)”頁(yè)面轉(zhuǎn)場(chǎng):自定義2“動(dòng)效
本節(jié)實(shí)現(xiàn)的效果,頁(yè)面入場(chǎng)時(shí)淡入和放大,同時(shí)順時(shí)針旋轉(zhuǎn);退場(chǎng)時(shí)淡出和縮小,同時(shí)逆時(shí)針旋轉(zhuǎn)。效果如圖所示:
在FullCustomTransition.ets的Column組件中添加TransitionElement組件,并且定義pageTransition方法。給Stack組件添加opacity、scale、rotate屬性,定義變量animValue用來(lái)控制Stack組件的動(dòng)效,在PageTransitionEnter和PageTransitionExit組件中動(dòng)態(tài)改變myProgress的值。
// FullCustomTransition.ets
@Entry
@Component
struct FullCustomTransition {
@State animValue: number = FULL_CUSTOM_TRANSITION_DEFAULT_ANIM_VALUE;
build() {
Column() {
TransitionElement()
}
.opacity(this.animValue)
.scale({ x: this.animValue, y: this.animValue })
.rotate({
z: FULL_CUSTOM_TRANSITION_ROTATE_Z,
angle: FULL_CUSTOM_TRANSITION_ANGLE * this.animValue
})
}
/**
* 頁(yè)面轉(zhuǎn)場(chǎng)通過(guò)全局pageTransition方法進(jìn)行配置轉(zhuǎn)場(chǎng)參數(shù)
*
* 進(jìn)場(chǎng)過(guò)程中會(huì)逐幀觸發(fā)onEnter回調(diào),入?yún)閯?dòng)效的歸一化進(jìn)度(0 - 1)
* 進(jìn)場(chǎng)過(guò)程中會(huì)逐幀觸發(fā)onExit回調(diào),入?yún)閯?dòng)效的歸一化進(jìn)度(0 - 1)
*/
pageTransition() {
PageTransitionEnter({ duration: TRANSITION_ANIMATION_DURATION, curve: Curve.Smooth })
.onEnter((type?: RouteType, progress?: number) = > {
if (!progress) {
return;
}
this.animValue = progress;
});
PageTransitionExit({ duration: TRANSITION_ANIMATION_DURATION, curve: Curve.Smooth })
.onExit((type?: RouteType, progress?: number) = > {
if (!progress) {
return;
}
this.animValue = FULL_CUSTOM_TRANSITION_DEFAULT_ANIM_VALUE - progress;
});
}
}
組件內(nèi)轉(zhuǎn)場(chǎng)
本節(jié)實(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)效,需要配合animateTo才能生效。動(dòng)效時(shí)長(zhǎng)、曲線、延時(shí)跟隨animateTo中的配置。
- 在ComponentTransition.ets文件中,新建Image子組件,并添加兩個(gè)transition屬性,分別用于定義組件的添加動(dòng)效和移除動(dòng)效。
// ComponentTransition.ets Image($r('app.media.bg_element')) .TransitionEleStyles() .transition({ type: TransitionType.Insert, scale: COMPONENT_TRANSITION_SCALE, opacity: COMPONENT_TRANSITION_OPACITY }) .transition({ type: TransitionType.Delete, rotate: COMPONENT_TRANSITION_ROTATE, opacity: COMPONENT_TRANSITION_OPACITY })
- 在ComponentTransition代碼中,定義一個(gè)isShow變量,用于控制Image子組件的添加和移除,在Button組件的onClick事件中添加animateTo方法,來(lái)使Image子組件子組件動(dòng)效生效。
// ComponentTransition.ets @State isShow: boolean = false; Button($r('app.string.Component_transition_toggle')) .height(DimensionUtil.getVp($r('app.float.element_trans_btn_height'))) .width(DimensionUtil.getVp($r('app.float.element_trans_btn_width'))) .fontColor(Color.White) .backgroundColor($r('app.color.light_blue')) .onClick(() = > { animateTo({ duration: TRANSITION_ANIMATION_DURATION }, () = > { this.isShow = !this.isShow; }) })
共享元素轉(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)畫曲線和延時(shí),實(shí)現(xiàn)步驟如下:
- 在ShareItem.ets中給Image組件設(shè)置sharedTransition屬性,組件轉(zhuǎn)場(chǎng)id設(shè)置為“SHARE_TRANSITION_ID”。
// ShareItem.ets Image($r('app.media.bg_transition')) .width(FULL_LENGTH) .height(DimensionUtil.getVp($r('app.float.share_item_element_height'))) .borderRadius(DimensionUtil.getVp($r('app.float.share_item_radius'))) .margin({ bottom: DimensionUtil.getVp($r('app.float.share_item_element_margin_bottom')) }) .sharedTransition(SHARE_TRANSITION_ID, { duration: TRANSITION_ANIMATION_DURATION, curve: Curve.Smooth, delay: SHARE_ITEM_ANIMATION_DELAY }) .onClick(() = > { router.pushUrl({ url: SHARE_PAGE_URL }) .catch((err: Error) = > { hilog.error(DOMAIN, PREFIX, FORMAT, err); }); })
- 在SharePage.ets中給Image組件設(shè)置sharedTransition屬性,組件轉(zhuǎn)場(chǎng)id設(shè)置為“SHARE_TRANSITION_ID”。
// SharePage.ets @Entry @Component struct SharePage { build() { Column() { TransitionElement({ imgFit: ImageFit.Cover }) .sharedTransition(SHARE_TRANSITION_ID, { duration: SHARE_ITEM_DURATION, curve: Curve.Smooth, delay: SHARE_ITEM_ANIMATION_DELAY }) } } }
審核編輯 黃宇
-
開(kāi)發(fā)板
+關(guān)注
關(guān)注
25文章
5032瀏覽量
97371 -
HarmonyOS
+關(guān)注
關(guān)注
79文章
1973瀏覽量
30143 -
OpenHarmony
+關(guān)注
關(guān)注
25文章
3713瀏覽量
16254 -
RK3568
+關(guān)注
關(guān)注
4文章
514瀏覽量
5034
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論