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
    +关注

    关注

    25

    文章

    3710

    浏览量

    16247

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

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

收藏 人收藏

    评论

    相关推荐

    何在MSP430™实现内置振荡器的高精度定时器

    电子发烧友网站提供《如何在MSP430™实现内置振荡器的高精度定时器.pdf》资料免费下载
    发表于 09-14 11:10 0次下载
    如<b class='flag-5'>何在</b>MSP430™<b class='flag-5'>上</b><b class='flag-5'>实现</b>内置振荡器的高精度定时器

    何在DRA821U使用Linux实现快速引导

    电子发烧友网站提供《如何在DRA821U使用Linux实现快速引导.pdf》资料免费下载
    发表于 09-03 10:11 0次下载
    如<b class='flag-5'>何在</b>DRA821U<b class='flag-5'>上</b>使用Linux<b class='flag-5'>实现</b>快速引导

    第二届大会回顾第25期 | OpenHarmony的Python设备应用开发

    Python以其简单、易学和功能强大而闻名,有着广泛的用户群体。采用Python开发有助于降低OpenHarmony的学习门槛。如何在OpenHarmony用Python开发设备应用
    的头像 发表于 08-27 11:53 673次阅读
    第二届大会回顾第25期 | <b class='flag-5'>OpenHarmony</b><b class='flag-5'>上</b>的Python设备应用开发

    图片动画控件和Video image控件的使用方法

    在UI开发过程中,序列基本是绕不开的,AWTK 支持多种方法实现序列显示,本文介绍图片动画控件和Video image控件的使用方法。
    的头像 发表于 08-06 16:44 842次阅读
    图片<b class='flag-5'>动画</b>控件和Video image控件的使用方法

    【AWTK使用经验】如何实现序列动画

    目前想在AWTK中显示炫酷流畅的图片动画,此时可以用video_image控件来播放序列动画。本篇文章将介绍该控件的原理和使用方法。图1ZTP800示教器运行v
    的头像 发表于 07-18 08:25 398次阅读
    【AWTK使用经验】如何<b class='flag-5'>实现</b>序列<b class='flag-5'>帧</b><b class='flag-5'>动画</b>

    OpenHarmony之开机优化

    对其进行详细的性能分析,从而优化系统启动速度和运行效率。 三丶开机优化 开机优化的主要目的是为了快速启动开机动画和退出开机动画(显示桌面)。所以在优化之前,我们需要了解一下OpenHarmony系统中
    发表于 07-01 16:39

    通过视频提取及批量取模转换实现基于STC32的点阵LED动画播放

    通过视频提取及批量取模转换实现基于STC32的点阵LED动画播放
    的头像 发表于 06-27 02:16 374次阅读
    通过视频<b class='flag-5'>帧</b>提取及批量取模转换<b class='flag-5'>实现</b>基于STC32的点阵LED<b class='flag-5'>动画</b>播放

    鸿蒙ArkTS声明式组件:ImageAnimator

    提供动画组件来实现播放图片的能力,可以配置需要播放的图片列表,每张图片可以配置时长。
    的头像 发表于 06-24 11:18 517次阅读
    鸿蒙ArkTS声明式组件:ImageAnimator

    何在Openharmony实现USB复合设备

    如何让Openharmony设备HDC接口(OTG接口)作为一个复合设备,实现HDC(HDC:鸿蒙设备连接器) + CDC ACM(USB 虚拟串口),而设备本身支持HDC。所以需要增加CDC ACM(USB 虚拟串口)。
    的头像 发表于 06-13 15:03 1581次阅读
    如<b class='flag-5'>何在</b><b class='flag-5'>Openharmony</b>中<b class='flag-5'>实现</b>USB复合设备

    SBC3568启动升级,灵活更换动画logo

    IDO-SBC3568-V1更换开机logo和开机动画今天小智将会带着大家体验如何在openharmonysdk内替换开机logo和动态动画。Q如何更换开机logo?开机logo分为u
    的头像 发表于 05-25 08:32 429次阅读
    SBC3568启动升级,灵活更换<b class='flag-5'>动画</b>logo

    何在OpenHarmony设置静态IP?

    介绍本文适用于所有RK3566/RK3568/RK3588平台产品在OpenHarmony系统设置静态IP。本文以PurplePiOH开发板为例,在OpenHarmony系统上进行设置。触觉智能
    的头像 发表于 05-12 08:32 732次阅读
    如<b class='flag-5'>何在</b><b class='flag-5'>OpenHarmony</b>设置静态IP?

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

    请求动画 请求动画时通过requestAnimationFrame函数回调,在调用该函数
    发表于 05-06 14:11

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

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

    HarmonyOS开发案例:【动画

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

    鸿蒙开发之发动画

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