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

    关注

    33

    文章

    3971

    浏览量

    21341

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

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

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    HT for Web 动画 | 3D 动态渲染设计与实现

    动画凭借灵活的序列设计与精准时序控制,成为图扑软件 HT 可视化项目的核心视觉能力。结合完善的动画体系与性能优化方案,可打造高沉浸、高真实感的数字孪生场景,是
    的头像 发表于 03-24 11:05 169次阅读
    HT for Web <b class='flag-5'>帧</b><b class='flag-5'>动画</b> | 3D 动态渲染设计与<b class='flag-5'>实现</b>

    基于凌羽派的OpenHarmony北向应用开发:Hello World 示例应用

    和 animation 实现淡入淡出效果 交互逻辑 .onClick(() => { // 触发淡出动画 this.isFadingOut = true; ​ // 在淡出动画结束后更新文本索引
    发表于 02-25 11:25

    【原创】OpenHarmony系统投屏工具软件 - OpenHarmony_OHScrcpy使用推荐

    Android平台的scrcpy投屏工具。它能够将OpenHarmony设备的屏幕实时镜像到计算机,并提供设备控制功能。 实现原理框图 计算机侧(客户端) :基于Python跨平台实现 Ope
    发表于 01-22 18:34

    #OpenHarmony 镜像烧录

    OpenHarmony
    视美泰
    发布于 :2026年01月16日 09:42:36

    #OpenHarmony 系统概述

    OpenHarmony
    视美泰
    发布于 :2026年01月16日 09:39:20

    何在DGX Spark运行NVIDIA Omniverse

    首先感谢 Vigor 同学第一时间的分享,以下是具体如何在 DGX Spark 运行 Omniverse 的方法。
    的头像 发表于 12-17 10:13 893次阅读
    如<b class='flag-5'>何在</b>DGX Spark<b class='flag-5'>上</b>运行NVIDIA Omniverse

    智能显示模块可以播放动画吗?动画功能怎么实现,在哪可以添加?

    智能显示模块可以播放动画吗?动画功能怎么实现,在哪可以添加?
    发表于 11-08 08:57

    SGTools--动画控件--屏幕实现动画显示 就是这么简单

    详细步骤可以观看视频, 实现动画很简单,提前准备好gif文件和一个张背景图 使用SGTools工具,就可以制作动画界面啦 视频中屏幕型号是7寸 HMT070ATA-9C
    发表于 09-16 10:29

    【M-K1HSE开发板免费体验】相关源码之阅读和分析1-使用XComponent + Vsync 实现自定义动画

    介绍 XComponent 提供了应用在 native 侧调用 OpenGLES 图形接口的能力,本文主要介绍如何配合 Vsync 事件,完成自定义动画。在这种实现方式下,自定义动画的绘制不在 UI
    发表于 09-03 16:05

    分享---储能UI界面能量流动动画实现方法

    本文分享 工商业储能设备的UI界面中如何实现 能量流动的动画效果。 本例子效果 基于拓普微工业级 7寸屏电容串口屏(HMT070ETA-D型号)实现: 第1步:建立工程和页面 使用SGTools新建
    发表于 09-02 18:22

    使用 N9H30 时,如何在 emWin AppWizard 启用双缓冲功能?

    使用 N9H30 时,如何在 emWin AppWizard 启用双缓冲功能?
    发表于 09-01 06:40

    ElfBoard技术贴|如何在【RK3588】ELF 2开发板中实现自定义开机动画

    在嵌入式Linux系统的启动过程中,默认的文本启动日志往往缺乏良好的用户体验。为了提升设备启动时的视觉效果,可以通过psplash工具实现图形化开机动画,支持静态logo或动态动画显示
    的头像 发表于 07-25 09:37 1645次阅读
    ElfBoard技术贴|如<b class='flag-5'>何在</b>【RK3588】ELF 2开发板中<b class='flag-5'>实现</b>自定义开机<b class='flag-5'>动画</b>

    何在deepin 25使用Blender 4.5.0

    设计师、动画师以及 3D 爱好者们,你是否想过在 deepin 玩转全球顶尖开源 3D 创作套件 Blender?
    的头像 发表于 07-24 16:38 1803次阅读

    【EASY EAI Orin Nano开发板试用体验】使用Linux posix文件读取接口和LVGL的animimg(图像动画)控件实现动画播放以及

    【EASY EAI Orin Nano开发板试用体验】使用Linux posix文件读取接口和LVGL的animimg(图像动画)控件实现动画播放以及使用LVGL定时器实现摄像头图像显
    发表于 07-22 00:34

    基于小凌派RK2206开发板:OpenHarmony如何使用IoT接口控制UART外设

    1、实验简介本实验将演示如何在小凌派-RK2206开发板使用IOT库的UART接口,进行UART编程开发。例程将创建一个任务,通过配置UART引脚,实现UART读写操作。例程源代码:https
    的头像 发表于 04-22 14:22 1265次阅读
    基于小凌派RK2206开发板:<b class='flag-5'>OpenHarmony</b>如何使用IoT接口控制UART外设