ArkUI-动画

ArkUI-动画

  • 系统能力
    • 属性动画
    • 显式动画
  • 关键帧动画
    • 转场动画
    • 路径动画
    • 粒子动画
  • 资源调用
    • GIF动画
    • 帧动画
  • 三方库
    • Lottie
    • SVG
  • 提升动画的流畅度
    • 使用renderGroup
      • 概述
      • 使用约束

系统能力

属性动画

通过更改组件的属性值实现渐变过渡效果,例如缩放、旋转、平移等。支持的属性包括width、height、backgroundColor、opacity、scale、rotate、translate等。

@Entry
@Component
struct AttrAnimationExample {@State widthSize: number = 250@State heightSize: number = 100@State rotateAngle: number = 0@State flag: boolean = truebuild() {Column() {Button('change size').onClick(() => {if (this.flag) {this.widthSize = 150this.heightSize = 60} else {this.widthSize = 250this.heightSize = 100}this.flag = !this.flag}).margin(30).width(this.widthSize).height(this.heightSize).animation({duration: 2000,curve: Curve.EaseOut,iterations: 3,playMode: PlayMode.Normal})Button('change rotate angle').onClick(() => {this.rotateAngle = 90}).margin(50).rotate({ angle: this.rotateAngle }).animation({duration: 1200,curve: Curve.Friction,delay: 500,iterations: -1, // 设置-1表示动画无限循环playMode: PlayMode.Alternate,expectedFrameRateRange: {min: 20,max: 120,expected: 90,}})}.width('100%').margin({ top: 20 })}
}

请添加图片描述

显式动画

可以通过用户的直接操作或应用程序的特定逻辑来触发,例如按钮点击时的缩放动画、列表项展开时的渐变动画等。HarmonyOS提供了全局animateTo显式动画接口来指定由于闭包代码导致状态变化的插入过渡动效。

// xxx.ets
@Entry
@Component
struct AnimateToExample {@State widthSize: number = 250@State heightSize: number = 100@State rotateAngle: number = 0private flag: boolean = truebuild() {Column() {Button('change size').width(this.widthSize).height(this.heightSize).margin(30).onClick(() => {if (this.flag) {animateTo({duration: 2000,curve: Curve.EaseOut,iterations: 3,playMode: PlayMode.Normal,onFinish: () => {console.info('play end')}}, () => {this.widthSize = 150this.heightSize = 60})} else {animateTo({}, () => {this.widthSize = 250this.heightSize = 100})}this.flag = !this.flag})Button('change rotate angle').margin(50).rotate({ x: 0, y: 0, z: 1, angle: this.rotateAngle }).onClick(() => {animateTo({duration: 1200,curve: Curve.Friction,delay: 500,iterations: -1, // 设置-1表示动画无限循环playMode: PlayMode.Alternate,onFinish: () => {console.info('play end')},expectedFrameRateRange: {min: 10,max: 120,expected: 60,}}, () => {this.rotateAngle = 90})})}.width('100%').margin({ top: 5 })}
}

请添加图片描述

关键帧动画

在UIContext中提供keyframeAnimateTo接口来指定若干个关键帧状态,实现分段的动画。

// xxx.ets
import { UIContext } from '@kit.ArkUI';@Entry
@Component
struct KeyframeDemo {@State myScale: number = 1.0;uiContext: UIContext | undefined = undefined;aboutToAppear() {this.uiContext = this.getUIContext?.();}build() {Column() {Circle().width(100).height(100).fill("#46B1E3").margin(100).scale({ x: this.myScale, y: this.myScale }).onClick(() => {if (!this.uiContext) {console.info("no uiContext, keyframe failed");return;}this.myScale = 1;// 设置关键帧动画整体播放3次this.uiContext.keyframeAnimateTo({ iterations: 3 }, [{// 第一段关键帧动画时长为800ms,scale属性做从1到1.5的动画duration: 800,event: () => {this.myScale = 1.5;}},{// 第二段关键帧动画时长为500ms,scale属性做从1.5到1的动画duration: 500,event: () => {this.myScale = 1;}}]);})}.width('100%').margin({ top: 5 })}
}

请添加图片描述

转场动画

路径动画

指对象沿着指定路径进行移动的动画效果。通过设置路径可以实现视图沿着预定义的路径进行移动,例如曲线运动、圆周运动等,为用户呈现更加生动的交互效果。

// xxx.ets
@Entry
@Component
struct MotionPathExample {@State toggle: boolean = truebuild() {Column() {Button('click me').margin(50)// 执行动画:从起点移动到(300,200),再到(300,500),再到终点.motionPath({ path: 'Mstart.x start.y L300 200 L300 500 Lend.x end.y', from: 0.0, to: 1.0, rotatable: true }).onClick(() => {animateTo({ duration: 4000, curve: Curve.Linear }, () => {this.toggle = !this.toggle // 通过this.toggle变化组件的位置})})}.width('100%').height('100%').alignItems(this.toggle ? HorizontalAlign.Start : HorizontalAlign.Center)}
}

请添加图片描述

粒子动画

通过大量小颗粒的运动来形成整体动画效果。通过对粒子在颜色、透明度、大小、速度、加速度、自旋角度等维度变化做动画,来营造一种氛围感。

@Entry
@Component
struct ParticleExample {@StatemyCount : number = 100flag : boolean = false;build() {Column(){Stack() {Particle({particles:[{emitter:{particle:{type:ParticleType.IMAGE,//粒子类型config:{src:$r("app.media.book"),size:[10,10]},count: this.myCount,//粒子总数lifetime:10000,//粒子生命周期,单位mslifetimeRange:100//粒子生命周期取值范围,单位ms},emitRate:3,//每秒发射粒子数shape:ParticleEmitterShape.CIRCLE//发射器形状},color:{range:[Color.White,Color.White]//初始颜色范围},opacity:{range:[1.0,1.0],updater:{type:ParticleUpdater.CURVE,//变化方式为曲线变化config:[{from:0,//变化起始值to:1.0,//变化终点值startMillis:0,//开始时间endMillis:6000//结束时间},{from:1.0,to:.0,startMillis:6000,endMillis:10000}]}},scale:{range:[0.1,1.0],updater:{type:ParticleUpdater.CURVE,config:[{from: 0,to: 1.5,startMillis: 0,endMillis: 8000,curve: Curve.EaseIn}]}},acceleration:{speed:{range:[3,9],updater:{type: ParticleUpdater.CURVE,config:[{from:10,to:20,startMillis:0,endMillis:3000,curve:Curve.EaseIn},{from:10,to:2,startMillis:3000,endMillis:8000,curve:Curve.EaseIn}]}},angle:{range:[0,180],updater:{type:ParticleUpdater.CURVE,config:[{from:1,to:2,startMillis:0,endMillis:1000,curve:Curve.EaseIn},{from:50,to:-50,startMillis:1000,endMillis:3000,curve:Curve.EaseIn},{from:3,to:5,startMillis:3000,endMillis:8000,curve:Curve.EaseIn}]}}},spin:{range:[0.1,1.0],updater:{type:ParticleUpdater.CURVE,config:[{from: 0,to: 360,startMillis: 0,endMillis: 8000,curve: Curve.EaseIn}]}},},{emitter:{particle:{type:ParticleType.IMAGE,config:{src:$r('app.media.heart'),size:[10,10]},count: this.myCount,lifetime:10000,lifetimeRange:100},emitRate:3,shape:ParticleEmitterShape.CIRCLE},color:{range:[Color.White,Color.White]},opacity:{range:[1.0,1.0],//粒子透明度updater:{type:ParticleUpdater.CURVE,//透明度的变化方式是随机变化config:[{from:0,to:1.0,startMillis:0,endMillis:6000},{from:1.0,to:.0,startMillis:6000,endMillis:10000}]}},scale:{range:[0.1,1.0],updater:{type:ParticleUpdater.CURVE,config:[{from: 0,to: 2.0,startMillis: 0,endMillis: 10000,curve: Curve.EaseIn}]}},acceleration:{//加速度的配置,从大小和方向两个维度变化,speed表示加速度大小,angle表示加速度方向speed:{range:[3,9],updater:{type: ParticleUpdater.CURVE,config:[{from:10,to:20,startMillis:0,endMillis:3000,curve:Curve.EaseIn},{from:10,to:2,startMillis:3000,endMillis:8000,curve:Curve.EaseIn}]}},angle:{range:[0,180],updater:{type:ParticleUpdater.CURVE,config:[{from:1,to:2,startMillis:0,endMillis:1000,curve:Curve.EaseIn},{from:50,to:-50,startMillis:0,endMillis:3000,curve:Curve.EaseIn},{from:3,to:5,startMillis:3000,endMillis:10000,curve:Curve.EaseIn}]}}},spin:{range:[0.1,1.0],updater:{type:ParticleUpdater.CURVE,config:[{from: 0,to: 360,startMillis: 0,endMillis: 10000,curve: Curve.EaseIn}]}},},{emitter:{particle:{type:ParticleType.IMAGE,config:{src:$r('app.media.sun'),size:[10,10]},count: this.myCount,lifetime:10000,lifetimeRange:100},emitRate:3,shape:ParticleEmitterShape.CIRCLE},color:{range:[Color.White,Color.White]},opacity:{range:[1.0,1.0],updater:{type:ParticleUpdater.CURVE,config:[{from:0,to:1.0,startMillis:0,endMillis:6000},{from:1.0,to:.0,startMillis:6000,endMillis:10000}]}},scale:{range:[0.1,1.0],updater:{type:ParticleUpdater.CURVE,config:[{from: 0,to: 2.0,startMillis: 0,endMillis: 10000,curve: Curve.EaseIn}]}},acceleration:{speed:{range:[3,9],updater:{type: ParticleUpdater.CURVE,config:[{from:10,to:20,startMillis:0,endMillis:3000,curve:Curve.EaseIn},{from:10,to:2,startMillis:3000,endMillis:8000,curve:Curve.EaseIn}]}},angle:{range:[0,180],updater:{type:ParticleUpdater.CURVE,config:[{from:1,to:2,startMillis:0,endMillis:1000,curve:Curve.EaseIn},{from:50,to:-50,startMillis:1000,endMillis:3000,curve:Curve.EaseIn},{from:3,to:5,startMillis:3000,endMillis:8000,curve:Curve.EaseIn}]}}},spin:{range:[0.1,1.0],updater:{type:ParticleUpdater.CURVE,config:[{from: 0,to: 360,startMillis: 0,endMillis: 10000,curve: Curve.EaseIn}]}},}]}).width(300).height(300)}.width(500).height(500).align(Alignment.Center)}.width("100%").height("100%")}
}

请添加图片描述

资源调用

GIF动画

GIF动画可以在特定位置循环播放,为应用界面增添生动的视觉效果。在开发中,可以使用Image组件来实现GIF动画的播放。

帧动画

通过逐帧播放一系列图片来实现动画效果,在开发中可以使用ImageAnimator组件来实现帧动画的播放。

// xxx.ets
@Entry
@Component
struct ImageAnimatorExample {@State state: AnimationStatus = AnimationStatus.Initial@State reverse: boolean = false@State iterations: number = 1build() {Column({ space: 10 }) {ImageAnimator().images([{src: $r('app.media.img1')},{src: $r('app.media.img2')},{src: $r('app.media.img3')},{src: $r('app.media.img4')}]).duration(2000).state(this.state).reverse(this.reverse).fillMode(FillMode.None).iterations(this.iterations).width(340).height(240).margin({ top: 100 }).onStart(() => {console.info('Start')}).onPause(() => {console.info('Pause')}).onRepeat(() => {console.info('Repeat')}).onCancel(() => {console.info('Cancel')}).onFinish(() => {console.info('Finish')this.state = AnimationStatus.Stopped})Row() {Button('start').width(100).padding(5).onClick(() => {this.state = AnimationStatus.Running}).margin(5)Button('pause').width(100).padding(5).onClick(() => {this.state = AnimationStatus.Paused     // 显示当前帧图片}).margin(5)Button('stop').width(100).padding(5).onClick(() => {this.state = AnimationStatus.Stopped    // 显示动画的起始帧图片}).margin(5)}Row() {Button('reverse').width(100).padding(5).onClick(() => {this.reverse = !this.reverse}).margin(5)Button('once').width(100).padding(5).onClick(() => {this.iterations = 1}).margin(5)Button('infinite').width(100).padding(5).onClick(() => {this.iterations = -1 // 无限循环播放}).margin(5)}}.width('100%').height('100%')}
}

三方库

Lottie

//构建渲染上下文
private mainRenderingSettings: RenderingContextSettings = new RenderingContextSettings(true)
private mainCanvasRenderingContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.mainRenderingSettings)
build() {Column() {// 显示徽章List({ space: Constants.MIDDLE_SPACE }) {ForEach(ACHIEVE_IMAGE_LIST, (item: AchieveImage) => {ListItem() {Image(this.getShowImg(item))// 图片的属性值…// 点击事件.onClick(() => {if (this.learnedIds.includes(item.pathId)) {lottie.loadAnimation({container: this.mainCanvasRenderingContext,renderer: 'canvas',loop: false,autoplay: false,name: item.pathId,path: item.lottiePath})lottie.play()this.clickedItem = item;this.isShow = true;}})}, (item: AchieveImage) => JSON.stringify(item))}// 模态转场.bindContentCover(this.isShow,this.playLottieBuilder(),{ modalTransition: ModalTransition.ALPHA, backgroundColor: $r('app.color.achieve_background_color'), onDisappear: () => {lottie.destroy()}})// 列表属性…}// 列容器属性…}//模态转场后页面@Builder playLottieBuilder() {Column() {Column() {// 建立画布Canvas(this.mainCanvasRenderingContext).height('50%').width('80%').backgroundColor($r('app.color.achieve_background_color')).onReady(() => {if (this.clickedItem != null) {lottie.loadAnimation({container: this.mainCanvasRenderingContext,renderer: 'canvas',loop: false,autoplay: true,name: this.clickedItem.pathId,path: this.clickedItem.lottiePath})}}).onClick(() => {this.isShow = false;})}Column() {Button('知道啦').onClick(() => {this.isShow = false;})}}}
}

SVG

提升动画的流畅度

  • 使用系统提供的动画接口:系统接口经过精心设计和优化,能够在不同设备上提供流畅的动画效果,最大程度地减少丢帧率和卡顿现象。
  • 使用图形变换属性变化组件布局:通过对组件的图形变换属性进行调整,而不是直接修改组件的布局属性,可以减少不必要的布局计算和重绘操作,从而降低丢帧率,提升动画的流畅度和响应速度。
  • 参数相同时使用同一个animateTo:当多个动画的参数相同时,将相同动画参数的动画合并在一个动画闭包中并使用同一个animateTo方法进行处理能够有效减少不必要的计算和渲染开销。
  • 多次animateTo时统一更新状态变量:在进行多次动画操作时,统一更新状态变量可以避免不必要的状态更新和重复渲染,从而减少性能开销。

使用renderGroup

概述

renderGroup是组件通用方法,它代表了渲染绘制的一个组合。其核心功能就是标记组件,在绘制阶段将组件和其子组件的绘制结果进行合并并缓存,以达到复用的效果,从而降低绘制负载。首次绘制组件时,若组件被标记为启用renderGroup状态,将对组件和其子组件进行离屏绘制,将绘制结果进行缓存。此后当需要重新绘制组件时,就会优先使用缓存而不必重新绘制,从而降低绘制负载,优化渲染性能。组件渲染流程图如下所示:
在这里插入图片描述
在进行缓存更新时,需要满足以下三个条件:

  • 组件在当前组件树上。
  • 组件renderGroup被标记为true。
  • 组件内容被标脏。

在进行缓存清理时,需要满足以下任意条件:

  • 组件不存在于组件树上。
  • 组件renderGroup被标记为false。

具体缓存管理流程图如下所示:
在这里插入图片描述

使用约束

为了能使renderGroup功能生效,组件存在以下约束。

  • 组件内容固定不变:父组件和其子组件各属性保持固定,不发生变化。如果父组件内容不是固定的,也就是说其子组件中上存在某些属性变化或者样式变化的组件,此时如果使用renderGroup,那么缓存的利用率将大大下降,并且有可能需要不断执行缓存更新逻辑,在这种情况下,不仅不能优化卡顿效果,甚至还可能使卡顿恶化。例如:文本内容使用双向绑定的动态数据;图片资源使用gif格式;使用video组件播放视频。
  • 子组件无动效:由父组件统一应用动效,其子组件均无动效。如果子组件上也应用动效,那么子组件相对父组件就不再是静止的,每一帧都有可能需要更新缓存,更新逻辑同样需要消耗系统资源。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1523532.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

乐鑫 ESP32-P4 无线连接解决方案

ESP32-P4 是乐鑫信息科技推出的一款功能强大的芯片 (SoC) ,专为高性能的应用打造。尽管 ESP32-P4 集成了一系列先进特性,但它并未设置无线连接功能,因此需要额外的连接方案来满足嵌入式系统的多样化需求。乐鑫为 ESP32-P4 提供了三种主要的连…

2分钟学会使用createrepo制作本地yum仓库

华子目录 createrepo介绍实验主题实验前提实验前的准备1.server端配置yum网络源(这里以阿里云为主)2.server端配置本地yum源(需要挂载本地镜像)3.关闭selinux和firewalld4.安装createrepo包 server端实验步骤1.只下载,…

检测SSRF漏洞的工具

免责声明此文档仅限于学习讨论与技术知识的分享,不得违反当地国家的法律法规。对于传播、利用文章中提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,本文作者不为此承担任何责任,一旦造成后果请自行承担&…

Self-study Python Fish-C Note19 P62to63

类和对象 (part 2) 本节主要介绍 类和对象的构造函数、重写、钻石继承、Mixin及案例源码剖析(原视频P62-63)\ 构造函数 之前我们在函数章节里说,函数是可以通过参数来进行个性化定制的。类在实例化的时候其实也是支持个性化定制对象的。 定义类的时候…

idea的springboot里面的resources是什么

在IDEA(IntelliJ IDEA)中的Spring Boot项目中,resources目录扮演着非常重要的角色。这个目录主要用于存放项目的非代码资源,包括但不限于配置文件、静态资源文件(如图片、CSS、JavaScript等)、模板文件&…

如何用c++判断一个类型是vector

如何用c判断一个类型是vector 我们使用模板元编程来搞定 这里我们可以定义一个模板结构体 is_std_vector,并对其进行特化,以便专门处理 std::vector 类型。 . 下面是详细的实现和使用示例。 实现 is_std_vector 类型, 继承自false_type 首先&#xff…

EvoSuite使用总结

1.安装EvoSuite插件 以IDEA为例,在Plugins栏搜索EvoSuite后点击install,安装完成后重启IDEA 2.使用EvoSuite 选中文件右键选择Run EvoSuite 生成成功可以看到如下提示: 注意事项: 生成路径:src/test/java 使用juni…

数智时代敲门砖:华为云MaaS服务让中小企业AI应用如此简单

文|白 鸽 编|王一粟 19.9元的数字人、29.9元的云数据库、195元10卡时包的MaaS大模型服务...... 堪称企业级“双十一”的华为云828营销季,带着一众AI应用产品和云服务,杀疯了。 云计算叠加大模型的价格战,也正式进入…

HTTPS理论(SSL/TLS)

SSL安全套接层协议 为互联网通信提供加密和身份认证SSL3.0有漏洞,被TLS取代基于TCP的协议工作原理 握手:客户端hello;服务器hello(发送数字证书)(协商ssl版本,加密算法)数据传输连接…

JS笔记

9.3 1.数据类型 1.1.Object 对象 对象:一切皆对象 面向过程:按照时间的发生顺序,从上往下依次执行 对象对象:指挥对象做某件事 1.2.数据类型的检测 1.3.数据类型转换 1.自动转换:js会通过关系运算符&#xff0c…

ai聊天软件哪个好用?分享5款实用的智能聊天软件

从文字到语音,再到现在的智能AI聊天软件,我们见证了沟通方式的不断演进。 每天,我们都需要与家人、朋友、同事进行交流,而AI聊天软件的出现,无疑为我们的对话增添了一抹智能色彩。 那么,ai聊天软件下载哪…

Kettle--发送邮件

目录 新建转换 执行成功 新建demo 作业job 发送邮件配置 邮件服务器: 授权码获得 以163邮箱为例 新建转换 执行成功 新建demo 作业job 发送邮件配置 确定发件人和收件人邮箱 服务器设置 邮件服务器: 邮件服务商SMTP服务器地址SMTP端口(…

图像边缘检测技术详解:利用OpenCV实现Sobel算子

图像边缘检测技术详解:利用OpenCV实现Sobel算子 前言Sobel算子的原理代码演示结果展示结语 前言 在数字图像处理的广阔领域中,边缘检测技术扮演着至关重要的角色。无论是在科学研究、工业自动化,还是在日常生活中的智能设备中,我们…

我的大模型岗位面试总结!太卷了!!!—我面试了24家大模型岗位 只拿了9个offer!

这段时间面试了很多家(共24家,9个offer,简历拒了4家,剩下是面试后拒的),也学到了超级多东西。 大模型这方向真的卷,面试时好多新模型,新paper疯狂出,东西出的比我读的快…

HiGPT:异构图语言模型的突破

人工智能咨询培训老师叶梓 转载标明出处 人工智能领域的一大挑战是如何从海量复杂的数据中提取有价值的信息,特别是在处理异构图数据时。异构图由多种类型的节点和边组成,它们之间的相互关系丰富而复杂。传统的图神经网络(GNNs)在…

年薪80万,成功入职字节跳动!

前言: 最近AI相关就业岗位爆了。。。无论是**华为、**百度、阿里、字节等互联网巨头,还是中小型的科技公司都在高薪挖 AI 人才。 上周找 字节的面试官朋友(职级3-1)要来了几套高质量AI****内部资料和2024吴恩达机器学习资料。既…

DeepMind MuJoCo——生成动态场景中的物体运动视频,模拟物理现象和动作生成

一、DeepMind MuJoCo介绍 DeepMind MuJoCo(Multi-Joint dynamics with Contact)是一个由 DeepMind 开发的高效物理仿真引擎,专门用于模拟具有复杂物理交互的机器人和物理系统。MuJoCo 能够在实时和非实时环境下进行高精度的物理仿真&#xf…

护眼台灯哪个牌子最好?五款央视公认最好的护眼灯分享

小时候,对正确用眼知识一无所知,也不明白何种光线环境对眼睛最为友善,结果如今的近视度数已濒临千度大关。虽然早已习惯佩戴眼镜的生活,但近视所带来的诸多不便仍旧在日常生活中无处不在。因此,对于家中孩子的视力健康…

开源的工作流系统突出优点总结

当前,想要实现高效率的办公,可以一起来了解低代码技术平台、开源的工作流系统的相关特点和功能优势。作为较受职场喜爱的平台产品,低代码技术平台拥有可视化才做界面、灵活、好维护操作等多个优势特点,在推动企业流程化办公的过程…

掀起社交娱乐新浪潮!AI如何应用到短视频APP?

随着人工智能技术的迅速发展和全球社交媒体用户的增长,AI视频生成应用正逐渐成为短视频社交媒体中的关键工具。AI工具不仅可以提高内容的创造效率,还能为用户带来全新的互动体验。 人工智能(AI)已经成为我们日常生活和工作中不可或…