课程地址: 黑马程序员HarmonyOS4+NEXT星河版入门到企业级实战教程,一套精通鸿蒙应用开发
(本篇笔记对应课程第 20 - 21节)
P20《19.ArkUI-属性动画和显式动画》
本节先来学习属性动画和显式动画:
在代码中定义动画,我们只需要定义好动画的起始状态和终止状态,ArkUI就会自动帮我们填充中间的动画状态,如下定义起始状态和终止状态:
1、属性动画:属性动画 animation() 需要注意:
(1)animation() 属性方法必须写在需要设置动画效果的样式语句之后,如下图animation()属性方法需要写在 position() 与 rotate() 之后,否则会没有效果;
(2)animation() 属性方法只会对一些特定的属性生效,如 width、height、opacity、backgroundColor、scale、rotate、translate 等属性;
(3)animation() 属性方法需要传递的参数如下:
下面来做一个“小鱼动画”的案例:添加一个“小鱼动画”的页面。
页面静态代码与效果如下:
用 animation() 属性动画的方式给小鱼图片添加动画效果,同时添加方向键控制小鱼坐标位置语句:
向左和向右时切换图片以保证小鱼头部朝前:
2、显式动画:通过全局 animateTo() 函数修改组件属性
在小鱼案例中使用全局 animateTo() 函数实现动画效果:animateTo() 是一个全局函数,可以直接调用:
总结:
本节主要讲了两种实现动画的方式:
1、属性动画:调用属性方法 animation()
2、显式动画:调用全局公共方法 animateTo()
第二种方式用得更普遍。
实践:
实践遇到的问题如下:
1、报错,仔细观察发现老师定义的小鱼图片src变量类型是 Resource,不是 ResourceSrc。改为 Resource后报错消失:
2、设置背景图大小与位置,尝试了几个相关属性:
通用属性文档查询:通用属性文档
https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V2/ts-universal-attributes-opacity-0000001427902432-V2
3、“The component you have selected is not displayed on the preview” 小鱼图片不显示,原因不明。更换webp格式图片为png格式图片,可以显示了。但之前案例中我使用过webp格式图片,显示正常。这里这个问题暂时不明白什么原因。
4、这个问题也很奇葩:animation() 对小鱼位置变化添加不上动画效果,只对向左和向右时切换小鱼图片src可以添加上动画效果。原因暂时没弄明白。
P21《20.ArkUI-组件转场动画》
想让组件具有插入或移除时的转场效果,就需要让组件有插入和移除的情景,比如条件渲染组件:
使用转场动画给小鱼添加动画效果:
1、第一步:给小鱼图片添加 transition() 入场动画效果:
第二步:在小鱼图片组件显示时添加 animateTo 函数控制:
页面间的转场动画效果可以查看官方文档:
实践:
本节实践代码:
import router from '@ohos.router'
@Styles function btnStyle(){
.backgroundColor('rgba(0,0,0,0.2)')
}
@Entry
@Component
struct AnimationPage {
// 小鱼坐标
@State fishX: number = 200
@State fishY: number = 180
// 小鱼角度
@State angle: number = 0
// 小鱼图片
@State src:Resource = $r('app.media.fish')
// 是否开始游戏
@State isBegin:boolean = false
build() {
Row() {
Column() {
Stack(){
// 返回按钮
Button('返回')
.position({x:0,y:0})
.btnStyle()
.onClick(()=>{
router.back()
})
// 开始游戏按钮
if(!this.isBegin){
Button('开始游戏')
.onClick(()=>{
animateTo(
{duration:1000},
()=>{
this.isBegin = true
}
)
})
}else{
// 小鱼图片
Image(this.src)
.width('80')
.position({x: this.fishX - 40, y: this.fishY - 40})
// .animation({duration:500, tempo:1})
.transition({
type:TransitionType.Insert,
opacity:0,
translate:{x: -200}
})
}
// 操作按钮
Row(){
Button('←')
.btnStyle()
.type(ButtonType.Circle)
.onClick(()=>{
animateTo(
{ duration:500 },
()=>{
this.src = $r('app.media.fish_left')
this.fishX -= 40
}
)
})
Column({
space:20
}){
Button('↑')
.btnStyle()
.type(ButtonType.Circle)
.onClick(()=>{
animateTo(
{duration:500},
()=>{
this.fishY -= 40
}
)
})
Button('↓')
.btnStyle()
.type(ButtonType.Circle)
.onClick(()=>{
animateTo(
{duration:500},
()=>{
this.fishY += 40
}
)
})
}
Button('→')
.btnStyle()
.type(ButtonType.Circle)
.onClick(()=>{
animateTo(
{ duration:500 },
()=>{
this.src = $r('app.media.fish')
this.fishX += 40
}
)
})
}
.width(120)
.position({x:10,y:250})
.justifyContent(FlexAlign.Center)
}
.width('100%')
.height('100%')
}
.width('100%')
.height('100%')
}
.width('100%')
.height('100%')
.backgroundImage($r('app.media.fish_bg'),ImageRepeat.NoRepeat)
.backgroundImageSize(ImageSize.Cover)
.backgroundImagePosition(Alignment.Bottom)
}
}