鸿蒙应用开发-带你游遍动画王国
想必大家在孤独、无聊摸鱼、emo的时候,多少都会打开qq音乐和网易云来缓解情绪。今天我在学习的空余时间,打开qq音乐看见了这样的一幕:
动画无处不在,让我们一起来了解它吧!!!
今天呢,我将给大家讲述3种动画,分别是属性动画、显示动画、帧动画
属性动画animation
属性动画总体而言算是最简单的动画了,通常在我们的UI设计搭配.onClick(()=>{})。
!!!这里不是所有属性都能可以使用,只有==某些通用属性==变化时,才有效果。支持的属性包括
width、height、backgroundColor、opacity、scale(缩放非常常用)、rotate(旋转)translate(移动)等。
基础属性
duration设置动画时长,默认为1000mscurve设置动画曲线,详情见developer.huawei.com/consumer/cn…delay设置动画延迟执行的时长,默认为0msiterations设置动画的播放次数(默认值为1,==-1==表示无限次播放,次数为0时无动画效果)playMode动画播放模式,默认播放完成后重头开始播放(PlayMode.Normal),!!!如果想要来回变话可以用(PlayMode.Alternate)奇数次正放,偶数次倒放onFinish结束回调,动画播放完成时触发
核心步骤
- 声明相关(例如图片是否显示
isShow:boolean=true) - 将状态变量设置到相关可接口
- 通过属性动画接口开启属性动画
- 通过状态变量改变
UI界面
IU案例
首先,我们这里确定采用scale放大实现效果,所以绑定了****scaleXY,需要增加的功能就是点击一下图片,弹出放大后的图片。
在文章开头的动画中,因为图片在放大过程中有一个移动的效果,所以我加上了一个新的状态变量distance。
最终效果:
完整代码:
@Entry
@Component
struct Index {
@State
scaleXY:number=1//放大倍率
@State
distance:number=0//移动距离
build() {
Column(){
Image($r('app.media.img_IU'))
.width(80)
.scale({x:this.scaleXY,y:this.scaleXY})
.translate({y:this.distance})
.onClick(()=>{
this.scaleXY=4
this.distance=300
})
.animation({
duration:1000,
curve:Curve.Linear
})
}
.width("100%")
.height("100%")
}
}
显示动画animateTo
基本用法
属性动画animation是作为属性使用,而animateTo显示动画是一个系统的内置函数,可以直接调用,一般事件触发是一起使用,比如点击事件,滚动事件等等
这里注意,上面的与事件一起使用和animation中,位置不一样,仔细观察比较下图
案例
animateTo核心步骤与animation一致
首先,第一步我们先声明相关状态变量
然后,第二步我们将状态变量设置值到相关可动画属性接口
接着,第三步我们需要编写animateTo动画,先写动画属性
最后,第四步我们将对状态变量的逻辑操作写入箭头函数中
最后效果(播放一次):
(无限播放):
!!!这边很明显的可以看见onFinish()回调并没有触发,原因很简单:只有当动画结束时,才会触发
帧动画animator
介绍
animator是一个动画对象,用于管理和控制动画的播放。它可以通过设置不同的参数来控制动画的行为,如延时播放、播放次数、插值曲线等。animator可以通过createAnimator函数创建,并通过disposeAnimator函数销毁。
文档:developer.huawei.com/consumer/cn…
实现过程
- 由于
animator是一个对象,对象定义都需要类型,官方文档中给的是接口AnimatorResult,所以这里需要导入。
import {AnimatorResult} from '@kit.ArkUI'
@Entry
@Component
struct Index {
animator:AnimatorResult|undefined = undefined//没有创建动画为undefined
build(){}
}
-
创建动画样式,这边同样也要导入类
Animator,然后去使用他的create()方法,里面的动画属性在接口AnimatorOptions中,可以Ctrl+单击进去查看这8个属性缺一不可。有很多实例方法也存放接口AnimatorResult中,同样可以去查看。
import {Animator,AnimatorResult} from '@kit.ArkUI'
@Entry
@Component
struct Index {
animator:AnimatorResult|undefined = undefined//没有创建动画为undefined
@State
angle: number = 0 //旋转角度
//创建动画
create=()=>{
this.animator=Animator.create({
duration:10000, //播放时长
easing:'linear', //动画曲线
delay:0, //延迟事件
fill:'forwards' //动画结束后是否回到开始状态,forwards是保留结束状态
direction:'normal' //跟playMode一样,动画的播放方式
iterations:-1 //动画次数
begin:0 //动画插值起点
end:360 //动画插值终点
//这边举个例子,有张图片我要它实现每次转一圈,那么这里begin就是0,end就是360,然 后用一个状态变量储存angle,再旋转属性实现
})
this.animator.onFrame=(value)=>{
this.angle=value
}//接受到动画帧时回调,换句话说begin-->end就是0-->360的变化过程中,每变一次就赋值
状态变量angle
}
build(){}
}
- 编写UI界面,并将调用
animator对象
import {Animator,AnimatorResult} from '@kit.ArkUI'
@Entry
@Component
struct Index {
animator:AnimatorResult|undefined = undefined//没有创建动画为undefined
@State
angle: number = 0 //旋转角度
@State
num: number = 0 //这个次数是用来控制只有第一次生成动画
//创建动画
create=()=>{
this.animator=Animator.create({
duration:10000, //播放时长
easing:'linear', //动画曲线
delay:0, //延迟事件
fill:'forwards' //动画结束后是否回到开始状态,forwards是保留结束状态
direction:'normal' //跟playMode一样,动画的播放方式
iterations:-1 //动画次数
begin:0 //动画插值起点
end:360 //动画插值终点
//这边举个例子,有张图片我要它实现每次转一圈,那么这里begin就是0,end就是360,然 后用一个状态变量储存angle,再旋转属性实现
})
this.animator.onFrame=(value)=>{
this.angle=value
}//接受到动画帧时回调,换句话说begin-->end就是0-->360的变化过程中,每变一次就赋值状 态变量angle
}
build(){
Column() {
Image($r('app.media.startIcon'))
.width(200)
.borderRadius(100)
.rotate({
angle: this.angle
})
.onClick(() => {
this.num += 1
if (this.num == 1) {
this.create()
}
if (this.animator) { //这边判断是否为undefined
this.animator.play()
}
})
}
.width("100%")
.height("100%")
}
}
动画效果:
试一试
完整代码:
import { Animator, AnimatorResult } from '@kit.ArkUI'
@Entry
@Component
struct Index {
@State
angle1: number = 0
@State
isPause: boolean = true
animator: AnimatorResult | undefined = undefined
animator1: AnimatorResult | undefined = undefined
@State
angle: number = 0
@State
num: number = 0
@State
start: number = 0
@State
end: number = 30
create1 = () => {
this.animator = Animator.create({
duration: 10000,
easing: 'linear',
delay: 0,
fill: 'forwards',
direction: 'normal',
iterations: -1,
begin: 0,
end: 360
})
this.animator.onFrame = (value) => {
this.angle = value
}
}
create2 = () => {
this.animator1 = Animator.create({
duration: 1000,
easing: 'linear',
delay: 0,
fill: 'forwards',
direction: 'normal',
iterations: 1,
begin: this.start,
end: this.end
})
this.animator1.onFrame = (value) => {
this.angle1 = value
}
}
build() {
Column() {
Stack() {
Image($r('app.media.img_bell'))
.width(200)
.borderRadius(100)
.rotate({
angle: this.angle
})
Image(this.isPause == false ? $r('app.media.ic_suspend') : $r('app.media.ic_pause'))
.width(40)
.fillColor(Color.White)
.onClick(() => {
this.num += 1
if (this.num == 1) {
this.create1()
}
this.create2()
if (this.isPause == true && this.animator && this.animator1) {
this.isPause = false
this.start = 30
this.end = 0
this.animator.play()
this.animator1.play()
} else if (this.isPause == false && this.animator && this.animator1) {
this.isPause = true
this.start = 0
this.end = 30
this.animator.pause()
this.animator1.play()
}
console.log(this.start.toString())
console.log(this.end.toString())
})
Image($r("app.media.ic_wheat"))
.width(200)
.position({ x: -100 })
.rotate({
centerX: 80,
centerY: 20,
angle: this.angle1
})
}
}
.backgroundColor(Color.Pink)
.width("100%")
.height("100%")
}
}
这边,我是用了两个动画来写的,虽然有点烦但是何尝不是一种提升呢?大家可以使用更简单的方法(显示动画),但这种不可以不会哦!!!
不知不觉又要和大家说再见了,如果喜欢我的文章就请给我点个赞和关注吧!!!让我们下期见💕💕💕
我的歌单顺便也分享给大家:c6.y.qq.com/base/fcgi-b…
“本文正在参加华为鸿蒙有奖征文征文活动‘’