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

    关注

    31

    文章

    3927

    浏览量

    20725

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

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

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

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

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

    智能显示模块可以播放动画吗?动画功能怎么实现,在哪可以添加?
    发表于 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 1266次阅读
    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 1337次阅读

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

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

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

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

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

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

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

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

    S32K118EVB-Q064如何在firs后停止tx?

    您好,我需要使用 CAN2.0 标准 ID。我需要每 500 毫秒发送一个数据,但是当传输开始时,micro 不会在第一后停止,而是始终在传输。我正在使用 S32K118EVB-Q064。 如何在 firs
    发表于 04-09 07:22

    何在RAKsmart服务器实现企业AI模型部署

    AI模型的训练与部署需要强大的算力支持、稳定的网络环境和专业的技术管理。RAKsmart作为全球领先的服务器托管与云计算服务提供商,已成为企业部署AI模型的理想选择。那么,如何在RAKsmart服务器实现企业AI模型的部署呢?
    的头像 发表于 03-27 09:46 765次阅读

    何在SJA1110中配置IEEE802.1CB复制和冗余消除 (FRER)?

    嗨,我如何在 SJA1110 中配置 IEEE802.1CB 复制和冗余消除 (FRER),我需要实施进入端口 1 的数据的复制需要反映在端口 2 中,以及如何禁用进入端口 1 的数据可以在端口
    发表于 03-26 08:02

    用DeepSeek-R1实现自动生成Manim动画

    动画,视觉化呈现抽象的概念与原理。 什么是Manim?  Manim 是一个基于 Python 的动画引擎,专门用于创建高质量的数学相关动画,广泛应用于教育、科普等领域,帮助人们更直观地理解抽象的数学概念和原理。所有 有志于从事
    的头像 发表于 02-07 12:31 4650次阅读
    用DeepSeek-R1<b class='flag-5'>实现</b>自动生成Manim<b class='flag-5'>动画</b>