当前位置: 首页 > news >正文

HarmonyOS动画:属性动画、显示动画、转场动画

目录

  • 一、属性动画
  • 二、显示动画
  • 三、转场动画
    • 1.页面间转场
      • 设置退入场动画
      • 设置退入场平移效果
    • 2.组件内转场

一、属性动画

组件的某些通用属性变化时,可以通过属性动画实现渐变过渡效果。支持的属性包括width、height、backgroundColor、opacity、scale、rotate、translate等。
把animation接口加在要做属性动画的可动画属性后即可。animation只要检测到其绑定的可动画属性发生变化,就会自动添加属性动画。
animation(value:AnimateParam): T
设置组件的属性动画。

AnimateParam对象说明

  • duration:动画持续时间,默认为1000
  • tempo:动画速度为,值越大,速度越快,值越小,速度越小。为0时无动画效果。默认值:1.0;取值范围:[0, +∞)。
  • curve:Curve/string 动画曲线
  • delay:延迟播放时间
@Entry
@Component
struct AnimationExample {@State widthSize: number = 250;@State heightSize: number = 100;@State rotateAngle: number = 0;@State flag: boolean = true;@State space: number = 10;build() {Column() {Column({ space: this.space }) // 改变Column构造器中的space动画不生效.onClick(() => {if (this.flag) {this.widthSize = 150;this.heightSize = 60;this.space = 20; // 改变this.space动画不生效} else {this.widthSize = 250;this.heightSize = 100;this.space = 10; // 改变this.space动画不生效}this.flag = !this.flag;}).backgroundColor(Color.Black).margin(30).width(this.widthSize) // 只有写在animation前面才生效.height(this.heightSize) // 只有写在animation前面才生效.animation({duration: 2000,curve: Curve.EaseOut,iterations: 3,playMode: PlayMode.Normal})// .width(this.widthSize) // 动画不生效// .height(this.heightSize) // 动画不生效}}
}

二、显示动画

提供全局animateTo显式动画接口来指定由于闭包代码导致的状态变化插入过渡动效。同属性动画,布局类改变宽高的动画,内容都是直接到终点状态,例如文字、Canvas的内容等,如果要内容跟随宽高变化,可以使用renderFit属性配置。
animateTo(value: AnimateParam, event: () => void): void

显式动画接口。在需要动画时,显式调用该接口改变状态以产生动画。

  • 在组件出现时显示动画
@Entry
@Component
struct Index {@State widthSize: number = 250@State heightSize: number = 100@State flag: boolean = true@State rotateAngle: number = 0build() {Column() {Button('Change Size').onClick(() => {if (this.flag) {this.getUIContext()?.animateTo({duration: 2000,curve: Curve.EaseOut,iterations: 3,playMode: PlayMode.Normal},()=> {this.widthSize = 150this.heightSize = 60})} else {this.getUIContext()?.animateTo({},() => {this.widthSize = 250this.heightSize = 100})}this.flag = !this.flag}).width(this.widthSize).height(this.heightSize)Button('stop rotate').margin(50).rotate({x: 0,y:0,z:1,angle: this.rotateAngle}).onAppear(() => {this.getUIContext()?.animateTo({duration: 1200,curve: Curve.Friction,delay: 500, //延迟播放时间iterations: -1, //无限循环次播放playMode: PlayMode.Alternate,//动画在奇数次(1、3、5...)正向播放,在偶数次(2、4、6...)反向播放。expectedFrameRateRange: { //期待帧率min: 10,max: 10,expected: 60}},() => {this.rotateAngle = 90})}).onClick(() => {this.getUIContext()?.animateTo({duration: 0}, ()=>{this.rotateAngle = 0})})}.width('100%').height('100%').justifyContent(FlexAlign.Center)}
}

在这里插入图片描述

三、转场动画

1.页面间转场

当路由(router)进行切换时,可以通过在pageTransition函数中自定义页面入场和页面退场的转场动效。

  • PageTransitionEnter(value: PageTransitionOptions)
    设置当前页面的自定义入场动效。
  • onEnter(event: PageTransitionCallback): PageTransitionEnterInterface
    逐帧回调,直到入场动画结束,progress从0变化到1。
  • PageTransitionExit(value: PageTransitionOptions)
    设置当前页面的自定义退场动效。继承自CommonTransition
  • onExit(event: PageTransitionCallback): PageTransitionExitInterface
    逐帧回调,直到出场动画结束,progress从0变化到1。

PageTransitionOptions对象说明
支持设备PhonePC/2in1TabletTVWearable
元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称类型说明
typeRouteType页面转场效果生效的路由类型。默认值:RouteType.None。
durationnumber动画的时长;单位:毫秒;默认值:1000;取值范围:[0, +∞)
curveCurve /string / ICurve动画曲线。推荐以Curve或ICurve形式指定。当类型为string时,为动画插值曲线,取值参考AnimateParam的curve参数。默认值:Curve.Linear
delaynumber动画延迟时长;单位:毫秒;默认值:0

设置退入场动画

  • Index.ets
@Entry
@Component
struct Index {@State opacity1: number = 1;@State scale1: number = 1;build() {Column() {Image($r('app.media.sunbg')).width('100%').height('100%')}.width('100%').height('100%').scale({x: this.scale1}).opacity(this.opacity1).onClick(() => {this.getUIContext().getRouter().pushUrl({url: 'pages/Page1'})})}pageTransition() {//设置当前页的自定义入场动效PageTransitionEnter({duration: 1200, curve: Curve.Linear})//逐帧回调,直至动画结束.onEnter((type: RouteType, progress: number ) => {if (type == RouteType.Push || type == RouteType.Pop) {this.opacity1 = progressthis.scale1 = progress //设置转场时的缩放效果}})//设置当前页的自定义退场动效PageTransitionExit({duration: 1200, curve: Curve.Ease}).onExit((type: RouteType, progress: number) => {if (type == RouteType.Push) {this.opacity1 = 1 - progressthis.scale1 = 1 - progress}})}}
  • Page.ets
@Entry
@Component
struct Page1 {@State opacity2: number = 1;@State scale2: number = 1;build() {Column() {Image($r('app.media.wubg')).width('100%').height('100%')}.width('100%').height('100%').scale({x: this.scale2}).opacity(this.opacity2).onClick(() => {this.getUIContext().getRouter().pushUrl({url: 'pages/Index'})})}pageTransition() {PageTransitionEnter({duration: 1200, curve: Curve.Linear}).onEnter((type: RouteType, progress: number ) => {if (type == RouteType.Push || type == RouteType.Pop) {this.scale2 = progress}this.opacity2 = progress})PageTransitionExit({duration: 1200, curve: Curve.Ease}).onExit((type: RouteType, progress: number) => {if (type == RouteType.Pop) {this.opacity2 = 1 - progressthis.scale2 = 1 - progress}})}
}

在这里插入图片描述

通过不同的退入场类型配置不同的退场,入场动画。

  • Index.ets
@Entry
@Component
struct Index {@State opacity1: number = 1;@State scale1: number = 1;build() {Column() {Image($r('app.media.sunbg')).width('100%').height('100%')}// .width('100%')// .height('100%')// .scale({x: this.scale1})// .opacity(this.opacity1).onClick(() => {this.getUIContext().getRouter().pushUrl({url: 'pages/Page1'})})}pageTransition() {//设置当前页的自定义入场动效PageTransitionEnter({duration: 1200}).slide(SlideEffect.Left)//设置当前页的自定义退场动效PageTransitionExit({duration: 1000}).translate({x: 100.0, y: 100.0}).opacity(0)}
}
  • Page.ets
@Entry
@Component
struct Page1 {@State opacity2: number = 1;@State scale2: number = 1;build() {Column() {Image($r('app.media.wubg')).width('100%').height('100%')}.width('100%').height('100%').scale({x: this.scale2}).opacity(this.opacity2).onClick(() => {this.getUIContext().getRouter().pushUrl({url: 'pages/Index'})})}pageTransition() {PageTransitionEnter({duration: 1000}).slide(SlideEffect.Left)PageTransitionExit({duration: 1200}).translate({x: 100.0, y: 100.0}).opacity(0)}
}

在这里插入图片描述

设置退入场平移效果

Index.ets

@Entry
@Component
struct Index {@State scale1: number = 1@State opacity1: number = 1build() {Column() {Button('页面').onClick(() => {this.getUIContext()?.getRouter().pushUrl({url: 'pages/Page1'})}).width(200).height(60).fontSize(36)Text('START').fontSize(36).textAlign(TextAlign.Center)}.scale({x: this.scale1}).opacity(this.opacity1).height('100%').width('100%').justifyContent(FlexAlign.Center)}pageTransition() {PageTransitionEnter({duration: 200}).slide(SlideEffect.START)PageTransitionExit({duration: 100}).slide(SlideEffect.START)}
}
@Entry
@Component
struct Page {@State scale1: number = 1;@State opacity1: number = 1;build() {Column() {Button('Page2').onClick(() => {this.getUIContext().getRouter().pushUrl({url: "pages/Index"});}).width(200).height(60).fontSize(36)Text('END').fontSize(36).textAlign(TextAlign.Center)}.scale({x: this.scale1}).opacity(this.opacity1).width('100%').height('100%').justifyContent(FlexAlign.Center)}// pageTransition() {//   PageTransitionEnter({duration: 200})//     .slide(SlideEffect.END)//   PageTransitionExit({duration: 100})//     .slide(SlideEffect.END)// }}

在这里插入图片描述

2.组件内转场

transition(value: TransitionOptions | TransitionEffect): T
组件插入显示和删除隐藏的过渡效果。

属性

名称说明
IDENTITY禁用转场效果。
OPACITY为组件添加透明度转场效果,出现时透明度从0到1、消失时透明度从1到0,相当于TransitionEffect.opacity(0)。
SLIDE从START边滑入,END边滑出。即在LTR模式下,从左侧滑入,右侧滑出;在RTL模式下,从右侧滑入,左侧滑出。
SLIDE_SWITCH指定出现时从右先缩小再放大侧滑入、消失时从左侧先缩小再放大滑出的转场效果。自带动画参数,也可覆盖动画参数,自带的动画参数时长600ms,指定动画曲线cubicBezierCurve(0.24, 0.0, 0.50, 1.0),最小缩放比例为0.8。
  • 使用不同接口实现图片的出现消失
@Entry
@Component
struct Index {//使用不同接口实现图片出现消失@State flag: boolean = false@State show: string = 'show'build() {Column() {Button(this.show).width(80).height(30).margin(30).onClick(() => {if (this.flag) {this.show = 'hide'} else {this.show = 'show'}this.getUIContext().animateTo({duration: 2000}, () => {this.flag = !this.flag})})if (this.flag) {Image($r('app.media.sunbg')).width(200).height(200)// .transition(TransitionEffect.OPACITY.animation({duration: 3000, curve: Curve.Ease}).combine(//   TransitionEffect.rotate({z: 1, angle: 180})// )).transition(TransitionEffect.asymmetric(TransitionEffect.OPACITY.animation({duration: 1000}).combine(TransitionEffect.rotate({z: 1, angle: 180}).animation({duration: 1000})),TransitionEffect.OPACITY.animation({delay: 1000, duration: 1000}).combine(TransitionEffect.rotate({z: 1, angle: 180}).animation({duration: 1000}))))Image($r('app.media.sunbg')).width(200).height(200).margin({top: 100}).transition(TransitionEffect.asymmetric(TransitionEffect.scale({x: 0, y: 0}),TransitionEffect.IDENTITY))}}.justifyContent(FlexAlign.Center).width('100%')}

在这里插入图片描述

  • 设置父组件为transition
@Entry
@Component
struct Index {// 设置父组件为transition@State flag: boolean = true;@State show: string = 'hide'build() {Column() {Button(this.show).margin({top:30}).width(80).height(30).onClick(() => {if (this.flag) {this.show = 'show'} else {this.show = 'hide'}this.flag = !this.flag})if (this.flag) {Column() {Row() {Image($r('app.media.sunbg')).width(150).height(150).margin({top: 50}).id('image1').transition(TransitionEffect.OPACITY.animation({duration: 1000}))}Image($r('app.media.sunbg')).width(150).height(150).margin({top: 50}).id('image2').transition(TransitionEffect.scale({x: 0, y: 0}).animation({duration: 1000}))Text('View').margin({top: 50})}.id('column1').transition(TransitionEffect.opacity(0.99).animation({duration: 1000}),(transition: boolean)=>{console.info('transition finish, transitionIn:'+transition)})}}.width('100%').justifyContent(FlexAlign.Center)}
}

在这里插入图片描述

http://www.dtcms.com/a/393627.html

相关文章:

  • Redis 持久化机制详解:RDB 与 AOF 原理与实践
  • 【嵌入式协议外设篇】-8×8 点阵屏
  • 【C++:STL】深入详解string类(一):从读文档开始
  • 电商项目实战总结
  • 22.元类、静态鸭子类型、抽象基类
  • 【论文速递】2025年第21周(May-18-24)(Robotics/Embodied AI/LLM)
  • Android 自定义电池组件(BatteryView)
  • 基于 Stripe/Metering 的用量计费:从 SLO 指标到账单流水
  • 如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘fastapi’ 问题
  • 论文阅读——隧道中毫米波MIMO信道特性的实验研究
  • The Library: 1靶场渗透
  • 23种设计模式之【装饰器模式】-核心原理与 Java实践
  • 动态规划中的背包问题:0/1 背包与完全背包的核心解析
  • PHP应用-组件框架前端模版渲染三方插件富文本编辑器CVE审计(2024小迪安全DAY30笔记)
  • uniapp 如何判断发的请求是网络异常uni.request
  • 学习:uniapp全栈微信小程序vue3后台 (25)
  • 23种设计模式之【原型模式】-核心原理与 Java实践
  • Netty 重放解码器ReplayingDecoder揭秘:重写轻量异常机制 和 ConstantPool
  • getgeo 生物信息 R语言 表型信息表”“样本信息表”或“临床信息表 phenodata phenotype data
  • OceanBase备租户创建(二):通过BACKUP DATABASE PLUS ARCHIVELOG
  • Linux文件打包压缩与软件安装管理完全指南
  • KingbaseES数据备份操作详解(图文教程)
  • 中断屏蔽实现方法-ARM内核
  • Kotlin 协程之 SharedFlow 与 StateFlow 深度解析
  • python爬虫(请求+解析+案例)
  • 111-Christopher-Dall_Arm-Timers-and-Fire:Arm架构计时器与半虚拟化时间
  • switch缺少break出现bug
  • 【自然语言处理】(3) --RNN循环神经网络
  • C# 中的 ReferenceEquals 方法
  • BERT:用于语言理解的深度双向Transformer预训练【简单分析】