电子说
在本教程中,我们将会通过一个简单的样例,学习如何基于ArkTS的声明式开发范式开发转场动画。其中包含页面间转场、组件内转场以及共享元素转场。效果如图所示:
说明: 本Codelab使用的display接口处于mock阶段,在预览器上使用会显示白屏现象,可选择在真机或模拟器上运行。
完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:
gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md
]本篇Codelab只对核心代码进行讲解,完整代码可以直接从gitee获取。
├──entry/src/main/ets // 代码区
│ ├──common
│ │ ├──constants
│ │ │ └──CommonConstants.ets // 公共常量类
│ │ └──utils
│ │ ├──DimensionUtil.ets // 屏幕适配工具类
│ │ └──GlobalContext.ets // 全局上下文工具类
│ ├──entryability
│ │ └──EntryAbility.ets // 程序入口类
│ ├──pages
│ │ ├──BottomTransition.ets // 底部滑出页面
│ │ ├──ComponentTransition.ets // 移动动画转场页面
│ │ ├──CustomTransition.ets // 放缩动画转场页面
│ │ ├──FullCustomTransition.ets // 旋转动画转场页面
│ │ ├──Index.ets // 应用首页
│ │ ├──ShareItem.ets // 共享元素转场部件
│ │ └──SharePage.ets // 共享元素转场页面
│ ├──view
│ │ ├──BackContainer.ets // 自定义头部返回组件
│ │ └──TransitionElement.ets // 自定义动画元素
│ └──viewmodel
│ └──AnimationModel.ets // 动画封装的model类
└──entry/src/main/resources // 资源文件目录
`HarmonyOS与OpenHarmony鸿蒙文档籽料:mau123789是v直接拿`
在这个任务中,我们将完成主界面的设计和开发,效果如图所示:
从上面效果图可以看出,主界面主要由5个相同样式的功能菜单组成,我们可以将这些菜单抽取成一个子组件Item。
// 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))
}
在BottomTransition申明pageTransition方法配置转场参数,其中PageTransitionEnter用于自定义当前页面的入场效果,PageTransitionExit用于自定义当前页面的退场效果。效果如图所示:
通过设置PageTransitionEnter和PageTransitionExit的slide属性为SlideEffect.Bottom,来实现BottomTransition入场时从底部滑入,退场时从底部滑出。
// BottomTransition.ets
@Entry
@Component
struct BottomTransition {
build() {
Column() {
TransitionElement()
}
}
/**
* 页面转场通过全局pageTransition方法进行配置转场参数
*
* SlideEffect.Bottom 入场时从屏幕下方滑入。
* SlideEffect.Bottom 退场时从屏幕下方滑出。
*/
pageTransition() {
PageTransitionEnter({ duration: TRANSITION_ANIMATION_DURATION, curve: Curve.Smooth }).slide(SlideEffect.Bottom);
PageTransitionExit({ duration: TRANSITION_ANIMATION_DURATION, curve: Curve.Smooth }).slide(SlideEffect.Bottom);
}
}
本节实现的效果,页面入场时为淡入和放大,退场时从右下角滑出。效果如图所示:
在CustomTransition.ets的Column组件中添加TransitionElement组件,并且定义pageTransition方法。
// CustomTransition.ets
@Entry
@Component
struct CustomTransition {
build() {
Column() {
TransitionElement()
}
}
/**
* 页面转场通过全局pageTransition方法进行配置转场参数
*
* 进场时透明度设置从0.2到1;x、y轴缩放从0变化到1
* 退场时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)
}
}
说明: translate设置页面转场时的平移效果,为入场时起点和退场时终点的值,和slide同时设置时默认生效slide。
本节实现的效果,页面入场时淡入和放大,同时顺时针旋转;退场时淡出和缩小,同时逆时针旋转。效果如图所示:
在FullCustomTransition.ets的Column组件中添加TransitionElement组件,并且定义pageTransition方法。给Stack组件添加opacity、scale、rotate属性,定义变量animValue用来控制Stack组件的动效,在PageTransitionEnter和PageTransitionExit组件中动态改变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
})
}
/**
* 页面转场通过全局pageTransition方法进行配置转场参数
*
* 进场过程中会逐帧触发onEnter回调,入参为动效的归一化进度(0 - 1)
* 进场过程中会逐帧触发onExit回调,入参为动效的归一化进度(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;
});
}
}
本节实现组件内转场动效,通过一个按钮来控制组件的添加和移除,呈现容器组件子组件添加和移除时的动效。效果如图所示:
组件转场主要通过transition属性方法配置转场参数,在组件添加和移除时会执行过渡动效,需要配合animateTo才能生效。动效时长、曲线、延时跟随animateTo中的配置。
// 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.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;
})
})
效果如图所示:
共享元素转场通过给组件设置sharedTransition属性来实现,两个页面的组件配置为同一个id,则转场过程中会执行共享元素转场。sharedTransition可以设置动效的时长、动画曲线和延时,实现步骤如下:
// 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
@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
})
}
}
}
审核编辑 黄宇
全部0条评论
快来发表一下你的评论吧 !