0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何在OpenHarmony上实现逐帧动画?

OpenHarmony技术社区 来源:OST开源开发者 2023-06-18 15:14 次阅读

逐帧动画是常见的一种动画呈现形式,本例就为大家介绍如何通过 translate(),setInterval(),clearAllInterval() 等方法实现逐帧动画。

效果呈现

8dd9fa18-0da6-11ee-962d-dac502259ad0.gif

本例最终效果如上图:

点击“run”按钮,火柴人开始走动。

点击“stop”按钮,火柴人停止走动。

运行环境

本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发:

IDE:DevEco Studio 3.1 Release

SDK:Ohos_sdk_public 3.2.12.5(API Version 9 Release)

实现思路

本例的实现有两个关键点: ①将连续走动的火柴人拆分为多帧静态图像,在固定的时间间隔内逐帧将图像移动到动画窗口,间隔时间要小于肉眼可察觉的时间。循环上述动作,就可以实现火柴人的走动动画。

火柴人静态图像如下:

8de69dfe-0da6-11ee-962d-dac502259ad0.png  

将背景图片以固定速度相对于火柴人走动方向反方向移动,从而实现火柴人向前走动的效果。

背景图如下:

8df42e92-0da6-11ee-962d-dac502259ad0.png

本例使用 translate() 控制火柴人的移动,用 backgroundImagePosition() 控制背景图的移动。 另外,通过 setInterval() 设置火柴人移动的时间间隔,通过 clearAllInterval() 清除移动。

开发步骤

①搭建 UI 框架

使用两个 Row 组件分别呈现背景图和火柴人,第二个 Row 组件作为第一个 Row 组件的子组件,父 Row 组件的背景设置为背景图,子 Row 组件中添加 Image 组件用来呈现火柴人单帧图像。

@Entry
@Component
exportdefaultstructframeAnimation{
build(){
Column(){
//父Row组件
Row(){
//子Row组件
Row(){
//通过Image组件显示火柴人图像
Image($r("app.media.man")).height(60).width(545.16)
}.width(100)
.justifyContent(FlexAlign.Start)
.alignItems(VerticalAlign.Top)
//截取显示与背景同等大小的区域,控制单个火柴人显示在画面中
.clip(true)
}
//添加背景图像
.backgroundImage($r("app.media.background"))
//保持宽高比进行缩小或者放大,使得图片两边都大于或等于显示边界。
.backgroundImageSize(ImageSize.Cover)
.width('100%')
.height(130)
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Bottom)
Row(){
//添加跑动按钮
Button('run')
.margin({right:10})
.type(ButtonType.Normal)
.width(75)
.borderRadius(5)
//添加停止按钮
Button('stop')
.type(ButtonType.Normal)
.borderRadius(5)
.width(75)
.backgroundColor('#ff0000')
}.margin({top:30,bottom:10})
}.width('100%').width('100%').padding({top:30})
}
}

②添加火柴人和背景图片的移动逻辑

通过状态变量设定火柴人和背景图片的位置,位置变化时可以实时刷新 UI 界面。

//火柴人位置变量
@StatemanPostion:{
x:number,
y:number
}={x:0,y:0}
//背景图位置变量
@StatetreePosition:{
x:number,
y:number
}={x:0,y:0}
给火柴人和背景图片添加位置属性。
Row(){
Row(){
Image($r("app.media.man"))
.height(60)
.width(545.16)
//通过translate实现火柴人的位移。绑定manPosition,用来改变火柴人位置。
.translate(this.manPostion)
}
...
}
.backgroundImage($r("app.media.background"))
.backgroundImageSize(ImageSize.Cover)
//通过backgroundImagePosition实现背景图片的位移。绑定treePosition,用来改变背景图片的位置。
.backgroundImagePosition(this.treePosition)
...

③为’‘run’'按钮和"stop"按钮绑定控制逻辑

构建火柴人和背景图片移动的方法,用来设定火柴人和背景图片每次移动的距离。 这里要注意火柴人每次移动的距离等于两个火柴人之间的间隔距离(像素值)。

//火柴人移动方法
manWalk(){
if(this.manPostion.x<= -517.902) {
    this.manPostion.x = 0
  } else {
    // 每次移动的距离为火柴人静态图像之间的间隔距离
    this.manPostion.x -= 129.69
  }
}
// 背景移动方法
treesMove() {
  if (this.treePosition.x <= -1215) {
    this.treePosition.x = 0
  } else {
    this.treePosition.x -= 20
  }
}

创建 doAnimation() 方法调用上述两个方法,以便在后续的定时器中使用。

doAnimation(){
this.manWalk()
this.treesMove()
}

通过 setInterval 为“run”按钮绑定走动逻辑。

Button('run')
.margin({right:10})
.type(ButtonType.Normal)
.width(75)
.borderRadius(5)
.onClick(()=>{
this.clearAllInterval()
//创建定时器,调用doAnimation方法,启动动画
lettimer=setInterval(this.doAnimation.bind(this),100)
this.timerList.push(timer)
})

通过 clearAllInterval 为“stop”按钮绑定停止逻辑。

Button('stop')
.type(ButtonType.Normal)
.borderRadius(5)
.width(75)
.backgroundColor('#ff0000')
.onClick(()=>{
//清理定时器,停止动画
this.clearAllInterval()
})

完整代码

本例完整代码如下:

@Entry
@Component
exportdefaultstructframeAnimation{
//火柴人位置变量
@StatemanPostion:{
x:number,
y:number
}={x:0,y:0}
//背景图位置变量
@StatetreePosition:{
x:number,
y:number
}={x:0,y:0}
//定时器列表,当列表清空时,动画停止
privatetimerList:number[]=[]

//火柴人移动方法
manWalk(){
if(this.manPostion.x<= -517.902) {
      this.manPostion.x = 0
    } else {
      this.manPostion.x -= 129.69
    }
  }
  // 背景移动方法
  treesMove() {
    if (this.treePosition.x <= -1215) {
      this.treePosition.x = 0
    } else {
      this.treePosition.x -= 20
    }
  }

  // 销毁所有定时器
  clearAllInterval() {
    this.timerList.forEach((timer: number) =>{
clearInterval(timer)
})
this.timerList=[]
}

doAnimation(){
this.manWalk()
this.treesMove()
}

build(){
Column(){
//父Row组件
Row(){
//子Row组件
Row(){
//通过Image组件显示火柴人图像
Image($r("app.media.man"))
.height(60)
.width(545.16)
//通过translate实现火柴人的位移。绑定manPosition变量,用来改变火柴人位置。
.translate(this.manPostion)
}
.width(100)
.justifyContent(FlexAlign.Start)
.alignItems(VerticalAlign.Top)
//截取显示与背景同等大小的区域,控制单个火柴人显示在画面中
.clip(true)
}
//添加背景图像
.backgroundImage($r("app.media.background"))
//保持宽高比进行缩小或者放大,使得图片两边都大于或等于显示边界。
.backgroundImageSize(ImageSize.Cover)
//通过backgroundImagePosition实现背景图片的位移。绑定treePosition,用来改变背景图片的位置。
.backgroundImagePosition(this.treePosition)
.width('100%')
.height(130)
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Bottom)

Row(){
//添加跑动按钮
Button('run')
.margin({right:10})
.type(ButtonType.Normal)
.width(75)
.borderRadius(5)
.onClick(()=>{
this.clearAllInterval()
lettimer=setInterval(this.doAnimation.bind(this),100)
this.timerList.push(timer)
})
//添加停止按钮
Button('stop')
.type(ButtonType.Normal)
.borderRadius(5)
.width(75)
.backgroundColor('#ff0000')
.onClick(()=>{
this.clearAllInterval()
})
}.margin({top:30,bottom:10})
}.width('100%').width('100%').padding({top:30})
}
}


审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • OpenHarmony
    +关注

    关注

    23

    文章

    3311

    浏览量

    15159

原文标题:OpenHarmony上实现逐帧动画

文章出处:【微信号:gh_834c4b3d87fe,微信公众号:OpenHarmony技术社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    OpenHarmony实战开发-如何实现组件动画

    ArkUI为组件提供了通用的属性动画和转场动画能力的同时,还为一些组件提供了默认的动画效果。例如,List的滑动动效,Button的点击动效,是组件自带的默认动画效果。在组件默认
    的头像 发表于 04-28 15:49 77次阅读
    <b class='flag-5'>OpenHarmony</b>实战开发-如何<b class='flag-5'>实现</b>组件<b class='flag-5'>动画</b>。

    HarmonyOS开发案例:【动画

    使用动画样式,实现几种常见动画效果:平移、旋转、缩放以及透明度变化。
    的头像 发表于 04-25 15:13 39次阅读
    HarmonyOS开发案例:【<b class='flag-5'>动画</b>】

    鸿蒙开发之发动画

    动画的原理是在一个时间段内,多次改变UI外观,由于人眼会产生视觉暂留,所以最终看到的就是一个“连续”的动画。UI的一次改变称为一个动画帧,对应一次屏幕刷新,而决定动画流畅度的一个重要指
    的头像 发表于 02-01 15:25 185次阅读
    鸿蒙开发之发<b class='flag-5'>动画</b>篇

    求助,如何在XMC4800实现CAN OPEN协议TLE9243QK_BASE_BOARD ?

    您好,我有一个关于XMC4800的问题,如何在XMC4800实现CAN OPEN协议 TLE9243QK_BASE_BOARD ?
    发表于 01-22 06:33

    HT for Web (Hightopo) 使用心得(5)- 动画实现

    其实,在 HT for Web 中,有多种手段可以用来实现动画。我们这里仍然用直升机为例,只是更换了场景。增加了巡游过程。 使用 HT 开发的一个简单网页直升机巡逻动画(Hightopo 使用心
    的头像 发表于 11-29 11:04 318次阅读
    HT for Web (Hightopo) 使用心得(5)- <b class='flag-5'>动画</b>的<b class='flag-5'>实现</b>

    Unity中国、Cocos为OpenHarmony游戏生态插上腾飞的翅膀

    大型3A游戏-倩女幽魂 在团结引擎成功移植的基础,网易的移植团队初期确定了“先做减法,再做加法”的目标,先实现包含了基础玩法和UI动画渲染的最小集目标。在最小集基础,再逐步去完善基
    发表于 10-23 16:15

    OpenHarmony应用开发—ArkUI组件集合

    ||||---imageAnimatorSample |||||---ImageAnimatorSample.ets// 播放图片 ||||---imageSample
    发表于 09-22 14:56

    Qt For OpenHarmony

    实现应用的迁移配置。 03► 技术难点分享 Qt本身是跨平台的框架,我们要把它跟OpenHarmony做移植,无非考虑几个问题:一是Qt应用程序的界面如何在OpenHarmony上进行
    发表于 09-15 15:39

    开发指导—利用组件&amp;插值器动画实现HarmonyOS动效

    ); _this.animation.play(); }; }, playAnimation() { var _this= this; //添加动画插值回调事件 this.animation.onframe
    发表于 09-05 11:33

    开源图形驱动在OpenHarmony的使用和落地

    。 03►开源图形驱动在OpenHarmony的移植 OpenHarmony驱动框架支持多种接入模式,能够实现南向硬件的快速部署。其中,显示框架支持Display_Gralloc
    发表于 08-31 18:07

    基于分级安全的OpenHarmony架构设计

    基金会OpenHarmony技术峰会——安全及机密计算分论坛 正 文 内 容 OpenHarmony是一个使能千行百业的操作系统,它是如何在数据的全生命周期里,基于分类分级的方式保护消费者的个人隐私和企业
    发表于 08-04 10:39

    使用Raspberry Pi和Arduino实现Web控制的LED动画

    电子发烧友网站提供《使用Raspberry Pi和Arduino实现Web控制的LED动画.zip》资料免费下载
    发表于 07-03 14:52 0次下载
    使用Raspberry Pi和Arduino<b class='flag-5'>实现</b>Web控制的LED<b class='flag-5'>动画</b>

    OpenHarmony 4.0 Beta1发布,邀您体验

    初夏之际,OpenAtom OpenHarmony(简称“OpenHarmony”) 4.0 Beta1版本如期而至。4.0 Beta1版本在3.2 Release版本基础,继续提升标准
    发表于 06-08 14:14

    Flash动画制作-1(动画和补间动画)(2)#多媒体技术

    FlaSh
    未来加油dz
    发布于 :2023年05月24日 10:39:32

    Flash动画制作-1(动画和补间动画)(1)#多媒体技术

    FlaSh
    未来加油dz
    发布于 :2023年05月24日 10:38:55