鸿蒙进阶-属性动画
hello大家好啊,这里是鸿蒙开天组,今天我们来学习鸿蒙中的动画属性。
先来说说动画~
属性值的变化,通常会引发 UI 的变化,结合动画可以让这个变化过程【更为流畅】,反之这个过程将在一瞬间完成,用户体验不好,观感突兀。这就是动画的作用:链接
HarmonyOS 中的动画主要分为:
- 属性动画
- 转场动画
- 组件动画
这么三类,一些和动画相关的其他细节咱们接着往下学。
今天咱们主要来学习属性动画。
属性动画-animation
接下来看看如何让咱们的应用动起来
组件的某些通用属性变化时,可以通过属性动画实现渐变过渡效果,提升用户体验。支持的属性包括width、height、backgroundColor、opacity、scale、rotate、translate等。
基本使用
使用动画的核心步骤如下:
- 声明相关状态变量
- 将状态变量设置到相关可动画属性方法上
- 通过属性动画接口开启属性动画(在属性动画上面的属性会应用动画)
- 通过状态变量改变UI界面
// 最核心写法,相关动画属性后续展开
组件
.属性1()
.属性2()
// .... animation 必须在需要动画的属性的后面
.animation({})
看完了概念,让我们来试一下~
基础模板
@Entry
@Component
struct Page01_animation {
// 1. 声明相关状态变量
@State translateY: number = 1
@State bgColor: ResourceColor = Color.Pink
@State fontColor: ResourceColor = '#0094ff'
@State fontWeight: number = 100
build() {
Column() {
Text('C')
.width(100)
.height(100)
.opacity(1)
.textAlign(TextAlign.Center)
// 2.将状态变量设置到相关可动画属性接口
.fontWeight(this.fontWeight)
.backgroundColor(this.bgColor)
.translate({ y: this.translateY })
Button('修改状态变量')
.onClick(() => {
// 4. 通过状态变量改变UI界面
this.bgColor = '#0094ff'
this.translateY = 100
this.fontColor = Color.Pink
this.fontWeight = 900
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.SpaceAround)
}
}
在上面的模板代码中,我们需要为容器添加动画,也就是给text的变量改变添加一个过渡。
为了方便理解,接下来的参考代码将变量改变的部分进行了函数封装,这样我们就可以得到这样一个结果 :
@Entry
@Component
struct Page01_animation {
// 1. 声明相关状态变量
@State translateY: number = 1
@State bgColor: ResourceColor = Color.Pink
@State fontColor: ResourceColor = '#0094ff'
@State fontWeight: number = 100
@State isOrNot: boolean = false
onclickEventEnd() {
// 4. 通过状态变量改变UI界面
this.bgColor = '#0094ff'
this.translateY = 100
this.fontColor = Color.Pink
this.fontWeight = 900
}
onclickEventStart() {
// 4. 通过状态变量改变UI界面
this.bgColor = Color.Pink
this.translateY = 1
this.fontColor = Color.Pink
this.fontWeight = 100
}
build() {
Column() {
Text('C')
.width(100)
.height(100)
.opacity(1)// 2.将状态变量设置到相关可动画属性接口
.fontWeight(this.fontWeight)
.backgroundColor(this.bgColor)
.textAlign(TextAlign.Center)
.translate({ y: this.translateY })
// 3.通过属性动画接口开启属性动画
.animation({})
Button('修改状态变量')
.onClick(() => {
if (this.isOrNot) {
this.onclickEventStart()
this.isOrNot = !this.isOrNot
} else {
this.onclickEventEnd()
this.isOrNot = !this.isOrNot
}
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.SpaceAround)
}
}
常用属性
可以通过动画参数(以对象的形式传递)来定制动画效果
组件
.animation({ 动画参数 })
名称 | 参数类型 | 必填 | 描述 |
duration | number | 否 | 动画时长,单位为毫秒。 默认值:1000 |
curve | string | Curve | ICurve | 否 | 设置动画曲线。 默认值:Curve.EaseInOut |
delay | number | 否 | 动画延迟播放时间。单位为毫秒,默认不延时播放。 默认值:0 取值范围:(-∞, +∞) |
iterations | number | 否 | 动画播放次数。 默认值:1 取值范围:[-1, +∞) 说明: 设置为-1时表示无限次播放。设置为0时表示无动画效果。 |
playMode | PlayMode | 否 | 动画播放模式,默认播放完成后重头开始播放。 默认值:PlayMode.Normal |
onFinish | () => void | 否 | 结束回调,动画播放完成时触发。 从API version 9开始,该接口支持在ArkTS卡片中使用。 |
动画曲线枚举值:
名称 | 描述 |
Linear | 表示动画从头到尾的速度都是相同的。 |
Ease | 表示动画以低速开始,然后加快,在结束前变慢,CubicBezier(0.25, 0.1, 0.25, 1.0)。 |
EaseIn | 表示动画以低速开始,CubicBezier(0.42, 0.0, 1.0, 1.0)。 |
EaseOut | 表示动画以低速结束,CubicBezier(0.0, 0.0, 0.58, 1.0)。 |
EaseInOut | 表示动画以低速开始和结束,CubicBezier(0.42, 0.0, 0.58, 1.0)。 |
FastOutSlowIn | 标准曲线,CubicBezier(0.4, 0.0, 0.2, 1.0)。 |
LinearOutSlowIn | 减速曲线,CubicBezier(0.0, 0.0, 0.2, 1.0)。 |
FastOutLinearIn | 加速曲线,CubicBezier(0.4, 0.0, 1.0, 1.0)。 |
ExtremeDeceleration | 急缓曲线,CubicBezier(0.0, 0.0, 0.0, 1.0)。 |
Sharp | 锐利曲线,CubicBezier(0.33, 0.0, 0.67, 1.0)。 |
Rhythm | 节奏曲线,CubicBezier(0.7, 0.0, 0.2, 1.0)。 |
Smooth | 平滑曲线,CubicBezier(0.4, 0.0, 0.4, 1.0)。 |
Friction | 阻尼曲线,CubicBezier(0.2, 0.0, 0.2, 1.0)。 |
playMode 播放模式枚举值
名称 | 描述 |
Normal | 动画正向播放。 |
Reverse | 动画反向播放。 |
Alternate | 先正向播放,再反向播放。 |
AlternateReverse | 先反向播放,后正向播放。 |
非常多的属性值,这里就不逐个尝试啦~有兴趣的可以自己尝试一下。
案例-折扣信息
接下来咱们来写一个小小的案例
需求:
动画效果:
- 元素大小切换
- 动画次数无限,元素【加载之后】开启动画
点击按钮触发
咱们先考虑如何实现点击开启动画,元素加载之后涉及到一个还未学习的知识点
核心步骤:有布局,有逻辑
1.布局:用 Text 方便调整实现布局
2.动画:animation
a.次数无限次
b.动画线性:匀速
c.改变的是缩放
i.宽高,定义在@State
3.如何触发:
a.点击触发
模板代码
@Entry
@Component
struct Page02_animationDemo1 {
build() {
Column({ space: 50 }) {
Text('全场低至一分购')
.fontSize(30)
.fontWeight(900)
.fontColor(Color.Red)
.backgroundColor('#e8b66d')
.padding(10)
.borderRadius(20)
}
.width('100%')
.height('100%')
.padding(20)
}
@Styles
fullSize() {
.width('100%')
.height('100%')
}
}
参考代码
@Entry
@Component
struct Page02_animationDemo1 {
// 1. 声明相关状态变量
@State scaleX: number = 1
@State scaleY: number = 1
build() {
Column({ space: 50 }) {
Text('全场低至一分购')
.fontSize(30)
.fontWeight(900)
.fontColor(Color.Red)
.backgroundColor('#e8b66d')
.padding(10)
.borderRadius(20)
// 2.将状态变量设置到相关可动画属性接口
.scale({
x: this.scaleX,
y: this.scaleY
})
// 3. 通过属性动画接口开启属性动画
.animation({
duration: 1000,
curve: Curve.Ease,
playMode: PlayMode.Alternate,
iterations: -1
})
.onClick(() => {
// 4.通过状态变量改变UI界面
this.scaleX = 1.3
this.scaleY = 1.3
})
}
.width('100%')
.height('100%')
.padding(20)
}
@Styles
fullSize() {
.width('100%')
.height('100%')
}
}
组件加载自动触发事件
如果要实现元素加载的时候就开始动画,可以使用挂载事件来实现,这是一个通用事件
链接
名称 | 功能描述 |
onAppear(event: () => void) | 组件挂载显示时触发此回调。 从API version 9开始,该接口支持在ArkTS卡片中使用。 |
onDisAppear(event: () => void) | 组件卸载消失时触发此回调。 从API version 9开始,该接口支持在ArkTS卡片中使用。 |
如何理解软件开发中的事件: 框架提供给开发者,在特定时机注册自定义逻辑的一种机制
接下来进行一个测试~
@Entry
@Component
struct Page03_appearAnddisAppear {
@State isShow: boolean = false
build() {
Column({ space: 50 }) {
Button('切换显示')
.onClick(() => {
this.isShow = !this.isShow
})
if (this.isShow) {
Text('我是文本')
.width('100%')
.onAppear(() => {
console.log('加载了')
})
.onDisAppear(() => {
console.log('卸载了')
})
}
}
.width('100%')
.height('100%')
.padding(20)
}
}
案例调整后的效果
@Entry
@Component
struct Page04_animationDemo1_event {
// 1. 声明相关状态变量
@State scaleX: number = 1
@State scaleY: number = 1
build() {
Column({ space: 50 }) {
Text('全场低至一分购')
.fontSize(30)
.fontWeight(900)
.fontColor(Color.Red)
.backgroundColor('#e8b66d')
.padding(10)
.borderRadius(20)// 2.将状态变量设置到相关可动画属性接口
.scale({
x: this.scaleX,
y: this.scaleY
})// 3. 通过属性动画接口开启属性动画
.animation({
duration: 1000,
curve: Curve.EaseInOut,
playMode: PlayMode.Alternate,
iterations: -1
})
.onAppear(() => {
// 4.通过状态变量改变UI界面
this.scaleX = 1.3
this.scaleY = 1.3
})
}
.width('100%')
.height('100%')
.padding(20)
}
@Styles
fullSize() {
.width('100%')
.height('100%')
}
}
今天的文章就到这里啦!这里是鸿蒙开天组,感谢大家的关注,咱们下篇文章再见!