HarmonyOS Next 属性动画和转场动画
在鸿蒙应用开发中,动画是提升用户体验的关键要素。通过巧妙运用动画,我们能让应用界面更加生动、交互更加流畅,从而吸引用户的注意力并增强其使用粘性。鸿蒙系统为开发者提供了丰富且强大的动画开发能力,其中属性动画是整个动画体系的核心基础。接下来,让我们深入探索鸿蒙动画。
鸿蒙动画体系概览
鸿蒙动画体系旨在为开发者打造全方位、多层次的动画创作环境。它不仅包含属性动画这种能够精确控制组件属性变化的基础类型,还拥有转场动画,用于实现界面间的平滑过渡,为用户带来自然且流畅的视觉切换体验。无论是组件的移动、旋转、缩放,还是界面的淡入淡出、滑动切换,鸿蒙动画体系都能轻松应对,助力开发者创建出极具吸引力的应用界面。
属性动画
可动画属性的多样选择
系统预定义可动画属性:鸿蒙系统贴心地为组件提供了一系列内置的可动画属性接口。例如,position
属性能够精准地调整组件在屏幕上的位置,使组件可以在不同坐标间平滑移动;scale
属性用于控制组件的缩放比例,让组件能够自如地放大或缩小;opacity
属性则决定了组件的透明度,实现淡入淡出等效果;blur
属性可赋予组件模糊效果,为界面增添独特的视觉风格。这些系统预定义的可动画属性,极大地简化了开发者创建常见动画效果的过程。
分类 | 说明 |
---|---|
布局属性 | 位置、大小、内边距、外边距、对齐方式、权重等。 |
仿射变换 | 平移、旋转、缩放、锚点等。 |
背景 | 背景颜色、背景模糊等。 |
内容 | 文字大小、文字颜色,图片对齐方式、模糊等。 |
前景 | 前景颜色等。 |
Overlay | Overlay属性等。 |
外观 | 透明度、圆角、边框、阴影等。 |
自定义可动画属性拓展:ArkUI 赋予开发者强大的自定义能力,通过@AnimatableExtend
装饰器,开发者能够从自定义绘制的内容中抽象出可动画属性。设想在开发一个音乐应用时,需要自定义绘制一个音量图标,并且希望该图标能够根据音量大小动态改变其大小、颜色或形状。借助@AnimatableExtend
装饰器,开发者就可以为这个原本不具备默认动画属性的自定义图标添加动画效果,从而满足特定的业务需求和创意设计。
丰富的属性动画接口
animateTo 接口:该接口主要作用于闭包内改变属性引起的界面变化,尤其在组件出现和消失的转场场景中表现出色。其原理是通过对比闭包前界面和闭包中状态变量引起的界面之间的差异,然后依据设定的动画参数对这些差异进行动画处理。它支持多次调用以及嵌套使用,这为开发者在处理复杂动画逻辑时提供了极大的灵活性。例如,在一个需要让组件同时进行平移、旋转和缩放,并且这些动画都使用相同动画参数的场景中,animateTo
就能发挥其优势,简洁高效地实现所需动画效果。
animation 接口:animation
接口作用于组件通过属性接口绑定的属性变化引起的界面变化。它能够敏锐地识别组件的可动画属性变化,当检测到绑定的可动画属性发生改变时,会自动为这些属性变化添加动画效果。值得注意的是,组件的接口调用遵循从下往上的执行顺序,animation
只会作用于在其之上的属性调用。这意味着开发者可以根据组件属性的调用顺序,轻松地对多个属性设置不同的animation
效果。比如,在一个组件既要移动又要改变透明度,且移动速度和透明度变化速度不同的场景中,通过animation
接口分别为translate
属性和opacity
属性设置不同的动画参数,就能精准实现所需的动画效果。
代码示例
下面通过一个具体的代码示例,展示如何使用animateTo
接口来实现属性动画。
@Entry
@Component
@Preview
struct AnimPage {@State animate: boolean = false;// 第一步: 声明相关状态变量@State rotateValue: number = 0; // 组件一旋转角度@State translateX: number = 0; // 组件二偏移量@State opacityValue: number = 1; // 组件二透明度build() {Column({ space: 20 }) {Row() {// 组件一Column() {Text("123")}.rotate({ angle: this.rotateValue }).backgroundColor('#317AF7').justifyContent(FlexAlign.Center).width(100).height(100).borderRadius(30).onClick(() => {this.getUIContext()?.animateTo({ curve: curves.springMotion(), duration: 3500 }, () => {this.animate = !this.animate;// 第三步:闭包内通过状态变量改变UI界面// 这里可以写任何能改变UI的逻辑比如数组添加,显隐控制,系统会检测改变后的UI界面与之前的UI界面的差异,对有差异的部分添加动画// 组件一的rotate属性发生变化,所以会给组件一添加rotate旋转动画this.rotateValue = this.animate ? 90 : 0;// 组件二的透明度发生变化,所以会给组件二添加透明度的动画this.opacityValue = this.animate ? 0.6 : 1;// 组件二的translate属性发生变化,所以会给组件二添加translate偏移动画this.translateX = this.animate ? 50 : 0;})})// 组件二Column() {Text("456")}.justifyContent(FlexAlign.Center).width(100).height(100).backgroundColor('#D94838').borderRadius(30).opacity(this.opacityValue).translate({ x: this.translateX }).animation({ curve: curves.springMotion(), duration: 3500 })}.width('100%').justifyContent(FlexAlign.Center)}}
}
在上述代码中,当用户点击Column
组件时,animate
状态变量会发生改变。依据animate
的值,rotateValue
(旋转角度)、translateX
(偏移量)和opacityValue
(透明度)这三个状态变量会相应地改变。由于opacity
、rotate
等属性绑定了animation
接口,并且设置了弹簧曲线curves.springMotion()
,所以当这些属性值发生变化时,会自动按照弹簧曲线的规律产生动画效果,使组件的旋转、平移和透明度变化呈现出自然的弹簧效果,为用户带来独特而生动的视觉体验。
效果如下:
转场动画
转场动画是指对将要出现或消失的组件做动画,对始终出现的组件做动画应使用属性动画。转场动画主要为了让开发者从繁重的消失节点管理中解放出来,如果用属性动画做组件转场,开发者需要在动画结束回调中删除组件节点。同时,由于动画结束前已经删除的组件节点可能会重新出现,还需要在结束回调中增加对节点状态的判断。
转场效果 | 说明 | 动画 |
---|---|---|
IDENTITY | 禁用转场效果。 | 无。 |
OPACITY | 默认的转场效果,透明度转场。 | 出现时透明度从0到1,消失时透明度从1到0。 |
SLIDE | 滑动转场效果。 | 出现时从窗口左侧滑入,消失时从窗口右侧滑出。 |
translate | 通过设置组件平移创建转场效果。 | 出现时为translate接口设置的值到默认值0,消失时为默认值0到translate接口设置的值。 |
rotate | 通过设置组件旋转创建转场效果。 | 出现时为rotate接口设置的值到默认值0,消失时为默认值0到rotate接口设置的值。 |
opacity | 通过设置透明度参数创建转场效果。 | 出现时为opacity设置的值到默认透明度1,消失时为默认透明度1到opacity设置的值。 |
move | 通过TransitionEdge创建从窗口哪条边缘出来的效果。 | 出现时从TransitionEdge方向滑入,消失时滑出到TransitionEdge方向。 |
asymmetric | 通过此方法组合非对称的出现消失转场效果。 - appear:出现转场的效果。 - disappear:消失转场的效果。 |
出现时采用appear设置的TransitionEffect出现效果,消失时采用disappear设置的TransitionEffect消失效果。 |
combine | 组合其他TransitionEffect。 | 组合其他TransitionEffect,一起生效。 |
animation | 定义转场效果的动画参数: - 如果不定义会跟随animateTo的动画参数。 - 不支持通过控件的animation接口配置动画参数。 - TransitionEffect中animation的onFinish不生效。 |
调用顺序时从上往下,上面TransitionEffect的animation也会作用到下面TransitionEffect。 |
代码示例
@Entry
@Component
@Preview
struct AnimPage {@State buttonScale: number = 1;@State buttonWidth: number = 100;@State showNewBtn: boolean = true// 创建默认透明度转场效果,并指定了springMotion(0.6, 0.8)曲线private opacityEffect: TransitionEffect = TransitionEffect.OPACITY.animation({ curve: curves.springMotion(0.6, 0.8) })// 创建默认平移转场效果, 左进右出private slideEffect: TransitionEffect = TransitionEffect.SLIDE.animation({ curve: curves.springMotion(0.6, 0.8) })private customEffect: TransitionEffect =// 创建默认透明度转场效果,并指定了springMotion(0.6, 0.8)曲线TransitionEffect.OPACITY.animation({ curve: curves.springMotion(0.6, 0.8) })// 通过combine方法,这里的动画参数会跟随上面的TransitionEffect,也就是springMotion(0.6, 0.8).combine(TransitionEffect.scale({ x: 0, y: 0 }))// 添加旋转转场效果,这里的动画参数会跟随上面带animation的TransitionEffect,也就是springMotion(0.6, 0.8).combine(TransitionEffect.rotate({ angle: 90 }))// 添加平移转场效果,这里的动画参数使用指定的springMotion().combine(TransitionEffect.translate({ y: 150 }).animation({ curve: curves.springMotion() }))// 添加move转场效果,这里的动画参数会跟随上面的TransitionEffect,也就是springMotion().combine(TransitionEffect.move(TransitionEdge.END))build() {Column({ space: 20 }) {Button("开始动画").onClick(() => {this.buttonScale = 1.5 / this.buttonScalethis.buttonWidth = 300 - this.buttonWidththis.showNewBtn = !this.showNewBtn}).width(this.buttonWidth).scale({ x: this.buttonScale, y: this.buttonScale }).animation({ curve: curves.springMotion() })if (this.showNewBtn) {Button("透明显隐(默认)").transition(this.opacityEffect)}if (this.showNewBtn) {Button("左进右出").transition(this.slideEffect)}if (this.showNewBtn) {Button("自定义").transition(this.customEffect)}}.width('100%')}
}
这段代码实现了一个包含按钮动画效果的界面。主要功能如下:
定义了按钮的缩放、宽度和显示状态。
创建了三种动画效果:透明度转场、平移转场和自定义组合转场。
点击“开始动画”按钮时,切换按钮的缩放和宽度,并切换新按钮的显示状态。
根据显示状态,动态展示三个带有不同动画效果的按钮。
运行效果:
通过以上对鸿蒙动画体系的介绍,特别是对属性动画和转场动画代码示例的实操,相信开发者们对鸿蒙动画开发有了更清晰的认识和更深入的理解。在实际开发中,充分利用这些动画特性,将为鸿蒙应用增添无限魅力,提升用户体验到新的高度。