当前位置: 首页 > news >正文

鸿蒙应用开发学习:改进小鱼动画实现按键一直按下时控制小鱼移动和限制小鱼移出屏幕

一、前言

近期我在学习鸿蒙应用开发,跟着B站UP主黑马程序员的视频教程做了一个小鱼动画应用,UP主提供的小鱼动画源代码仅仅实现了移动组件的功能,还存在一些问题,如默认进入页面是竖屏而页面适合横屏显示;真机测试发现手机的状态栏影响到了返回键对按键事件的响应;方向键不能响应一直按着的操作;还有小鱼会移出屏幕范围。

之前已经解决了强制横屏和隐藏手机状态栏,这次则是通过一番研究,实现了按键一直按下时控制小鱼移动和限制小鱼移出屏幕这两个功能。

二、实现方法

1. 一直按下方向键时控制小鱼移动

实现这一功能是在方向键下添加onTouch方法,对按键一直按下事件进行响应。在onTouch方法中还需要判断TouchType.Down事件和TouchType.Up事件。在TouchType.Down事件时,添加animateTo方法,实现按键时一直控制小鱼移动(需要通过setInterval方法设置定时任务让animateTo方法定期执行)。在TouchType.Up事件时,通过clearInterval清除定时任务,小鱼就不会一直移动了。以向右按键为例,改造后的代码如下:

Button('→').backgroundColor('#20101010').onClick(() => {              animateTo({ duration: 500 },() => {this.src = $r('app.media.fish')this.fishX += this.speed})}).onTouch((event: TouchEvent) => {if (event.type === TouchType.Down) {this.taskId = setInterval(() => {animateTo({ duration: 500 },() => {                      this.src = $r('app.media.fish')this.fishX += this.speed})}, 200)}if (event.type === TouchType.Up) {clearInterval(this.taskId)this.taskId = -1}})}.height(240).width(240).justifyContent(FlexAlign.Center).position({ x: 0, y: 120 })

2.限制小鱼移出屏幕

实现了上面的代码后,一直按下方向键,小鱼终于可以一直移动了,但往一个方向一直移动就会移出屏幕,为让小鱼不移出屏幕,还需要对按键操作事件进行判断,检查当前小鱼的位置,只有小鱼在限制的范围内才能执行animateTo方法移动小鱼。

按下向左方向键:对小鱼的X坐标(this.fishX)进行判断。屏幕左侧边界的X值为0,小鱼的大小为40(this.fishSize)。this.fishX是小鱼图片中心点的坐标,则当小鱼接触到屏幕左侧边界时,小鱼的中心点X坐标值为20。本软件中设置的小鱼的移动速度为20(this.speed),因此,我设置的判断条件是当this.fishX >= this.fishSize时,才能执行animateTo方法。当this.fishX == 40时,再移动一次this.fishX就变成了20,此时小鱼图片的左侧边缘正好接触到屏幕左边界。

按下向上方向键:对小鱼的Y坐标(this.fishY)进行判断。屏幕上边界Y值为0,小鱼大小为40。原理和按下向左方向机一样。我设置的判断条件是当this.fishY >= this.fishSize时,才能执行animateTo方法。

对于屏幕下方的边界和屏幕右侧的边界判断需要导入模块 import display from '@ohos.display' ,并在页面的onPageShow方法获取屏幕的尺寸信息。

onPageShow() {// 获取旋转的方向,具体可以查看对应文档let orientation = window.Orientation.LANDSCAPE;// 获取屏幕尺寸信息let promise = display.getAllDisplays()promise.then((data) => {console.info('设备屏幕信息:' + JSON.stringify(data));console.info('testTag', '屏幕宽度px:' + JSON.stringify(data[0].width));console.info('testTag', '屏幕高度px:' + JSON.stringify(data[0].height));this.screenWidth = px2vp(data[0].width)this.screenHeight = px2vp(data[0].height)console.info('testTag', '屏幕宽度vp:' + JSON.stringify(this.screenWidth));console.info('testTag', '屏幕高度vp:' + JSON.stringify(this.screenHeight));}).catch((err) => {console.error('错误信息:' + JSON.stringify(err));})}

按下向右方向机:对小鱼的X坐标(this.fishX)进行判断。屏幕右侧边界的X值为变量this.screenHeight, 则判定语句为 this.fishX <= this.screenHeight - this.fishSize 。只有符合该条件是才执行animateTo方法。

按下向下方向机:对小鱼的Y坐标(this.fishY)进行判断。屏幕右侧边界的Y值为变量this.screenWidth, 则判定语句为 this.fishY <= this.screenWidth - this.fishSize 。只有符合该条件是才执行animateTo方法。

这些判断语句都要添加到方向键的onClick方法和onTouch方法。

三、完整源代码

最后上这个文件的完整源代码:

import router from '@ohos.router';
import window from '@ohos.window'; // 用于强制设为横屏
import display from '@ohos.display'@Entry
@Component
struct Aquarium1Page {onPageShow() {// 获取旋转的方向,具体可以查看对应文档let orientation = window.Orientation.LANDSCAPE;try {// 设置屏幕旋转globalThis.windowClass.setPreferredOrientation(orientation, (err) => {console.log('testTag', `onPageShow函数中setPreferredOrientation方法错误码为${err}`)});} catch (exception) {console.error('设置失败: ' + JSON.stringify(exception));}// 获取屏幕尺寸信息let promise = display.getAllDisplays()promise.then((data) => {console.info('设备屏幕信息:' + JSON.stringify(data));console.info('testTag', '屏幕宽度px:' + JSON.stringify(data[0].width));console.info('testTag', '屏幕高度px:' + JSON.stringify(data[0].height));this.screenWidth = px2vp(data[0].width)this.screenHeight = px2vp(data[0].height)console.info('testTag', '屏幕宽度vp:' + JSON.stringify(this.screenWidth));console.info('testTag', '屏幕高度vp:' + JSON.stringify(this.screenHeight));}).catch((err) => {console.error('错误信息:' + JSON.stringify(err));})}onPageHide() {// 获取旋转的方向,具体可以查看对应文档let orientation = window.Orientation.PORTRAIT;try {// 设置屏幕旋转globalThis.windowClass.setPreferredOrientation(orientation, (err) => {console.log('testTag', `onPageHide函数中setPreferredOrientation方法错误码为${err}`)});} catch (exception) {console.error('设置失败: ' + JSON.stringify(exception));}}// 小鱼的位置@State fishX: number = 200@State fishY: number = 180// 小鱼的大小fishSize: number = 40// 小鱼角度@State angle: number = 0// 小鱼图片@State src: Resource = $r('app.media.fish')// 是否开始游戏@State isBegin: boolean = false// 小鱼的速度speed: number = 20// 用于控制Interval的idtaskId: number = -1// 屏幕尺寸screenWidth: number = px2vp(2000)screenHeight: number = px2vp(1080)build() {Row() {Stack() {Button('返回').position({ x: 20, y: 20 }).backgroundColor('#20101010').onClick(() => {router.back()})if (!this.isBegin) {Button('开始游戏').onClick(() => {animateTo({ duration: 1000 },() => {// 点击后显示小鱼this.isBegin = true})})} else {// 小鱼图片Image(this.src).position({ x: this.fishX - 20, y: this.fishY - 20 }).rotate({ angle: this.angle, centerX: '50%', centerY: '50%' }).width(this.fishSize).height(this.fishSize)//.animation({duration: 500, curve: Curve.Smooth}).transition({type: TransitionType.Insert,opacity: 0,translate: { x: -250 }})}// 操作按钮Row() {// 向左移动,小鱼身体不能超出屏幕范围Button('←').backgroundColor('#20101010').onClick(() => {if (this.fishX >= this.fishSize) {animateTo({ duration: 500 },() => {this.src = $r('app.media.fish_rev')this.fishX -= this.speed})}}).onTouch((event: TouchEvent) => {if (event.type === TouchType.Down) {this.taskId = setInterval(() => {animateTo({ duration: 500 },() => {if (this.fishX >= this.fishSize) {this.src = $r('app.media.fish_rev')this.fishX -= this.speed}})}, 200)}if (event.type === TouchType.Up) {clearInterval(this.taskId)this.taskId = -1}})Column({ space: 40 }) {// 向上和向下移动,小鱼的身体均不能超出屏幕范围Button('↑').backgroundColor('#20101010').onClick(() => {if (this.fishY >= this.fishSize) {animateTo({ duration: 500 },() => {this.fishY -= this.speed})}}).onTouch((event: TouchEvent) => {if (event.type === TouchType.Down) {this.taskId = setInterval(() => {animateTo({ duration: 500 },() => {if (this.fishY >= this.fishSize) {this.fishY -= this.speed}})}, 200)}if (event.type === TouchType.Up) {console.log("testTag", `停止向上,当前fishY为:${this.fishY}`)clearInterval(this.taskId)this.taskId = -1}})Button('↓').backgroundColor('#20101010').onClick(() => {if (this.fishY <= this.screenWidth - this.fishSize) {animateTo({ duration: 500 },() => {this.fishY += this.speed})}}).onTouch((event: TouchEvent) => {if (event.type === TouchType.Down) {this.taskId = setInterval(() => {animateTo({ duration: 500 },() => {if (this.fishY <= this.screenWidth - this.fishSize) {this.fishY += this.speed}})}, 200)}if (event.type === TouchType.Up) {console.log("testTag", `停止向下,当前fishY为:${this.fishY}`)clearInterval(this.taskId)this.taskId = -1}})}Button('→').backgroundColor('#20101010').onClick(() => {if (this.fishX <= this.screenHeight - this.fishSize) {animateTo({ duration: 500 },() => {this.src = $r('app.media.fish')this.fishX += this.speed})}}).onTouch((event: TouchEvent) => {if (event.type === TouchType.Down) {this.taskId = setInterval(() => {animateTo({ duration: 500 },() => {if (this.fishX <= this.screenHeight - this.fishSize) {this.src = $r('app.media.fish')this.fishX += this.speed}})}, 200)}if (event.type === TouchType.Up) {clearInterval(this.taskId)this.taskId = -1}})}.height(240).width(240).justifyContent(FlexAlign.Center).position({ x: 0, y: 120 })}.height('100%').width('100%')}.width('100%').height('100%').backgroundImage($r('app.media.underwater_cartoon')).backgroundImageSize({ height: '100%', width: '100%' })}
}

四、B站视频链接:

鸿蒙应用开发学习:改进小鱼动画实现按键一直按下时控制小鱼移动和限制小鱼移出屏幕-CSDN博客

相关文章:

鸿蒙应用开发学习:改进小鱼动画实现按键一直按下时控制小鱼移动和限制小鱼移出屏幕

一、前言 近期我在学习鸿蒙应用开发&#xff0c;跟着B站UP主黑马程序员的视频教程做了一个小鱼动画应用&#xff0c;UP主提供的小鱼动画源代码仅仅实现了移动组件的功能&#xff0c;还存在一些问题&#xff0c;如默认进入页面是竖屏而页面适合横屏显示&#xff1b;真机测试发现…...

紫光展锐5G扬帆出海 | Blade系列勇当拉美5G先锋

5G对拉丁美洲&#xff08;简称“拉美”&#xff09;绝大多数消费者来说还是一个新鲜技术。GSMA报告显示&#xff0c;过去五年&#xff0c;拉美运营商在移动网络方面的资本开支大部分用于部署4G网络。但在5G网络方面拉美也在积极大力投入中&#xff0c;紧跟全球5G发展大潮&#…...

如何设计一个高并发系统?

所谓高并发系统&#xff0c;是指能同时处理大量并发请求&#xff0c;并及时响应&#xff0c;从而保证系统的高性能和高可用 那么我们在设计一个高并发系统时&#xff0c;应该考虑哪些方面呢&#xff1f; 1. 搭建集群 如果你只部署一个应用&#xff0c;只部署一台服务器&…...

基于WebRTC技术的EasyRTC视频云服务系统在线视频客服解决方案

一、需求分析 随着互联网技术的发展&#xff0c;视频客服也成为服务行业的标配体验&#xff0c;基于WebRTC实时通信技术&#xff0c;客服人员与用户可以建立实时双向的视频交互与沟通。借助视频客服功能可以更加直观地了解用户的需求&#xff0c;提高沟通效率&#xff0c;并帮…...

黑马程序员——2022版软件测试——乞丐版——day04

目录&#xff1a; html介绍 前端三大核心html骨架标签注释标签 标题&#xff1a;h1~h6段落&#xff1a;p超链接a图片空格与换行布局标签列表input标签form标签作业 1.html介绍 前端三大核心 html:超文本标记语言&#xff0c;由一套标记标签组成标签&#xff1a; 单标签&…...

uniapp微信小程序投票系统实战 (SpringBoot2+vue3.2+element plus ) -创建图文投票实现

锋哥原创的uniapp微信小程序投票系统实战&#xff1a; uniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )_哔哩哔哩_bilibiliuniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )共计21条视频…...

Spring系列学习九、Spring MVC的使用

Spring MVC的使用 一、MVC设计模式概述二、Spring MVC的工作原理三、HandlerMapping和ViewResolver四、 处理表单、文件上传和异常处理五、前端页面&#xff08;View&#xff09;编写1. 引入Thymeleaf模板引擎2.页面相关的示例代码3.后端处理代码编写 六、总结 本章我们将与大家…...

开源内容管理系统Wagtail本地安装运行并结合内网穿透实现公网访问

文章目录 前言1. 安装并运行Wagtail1.1 创建并激活虚拟环境 2. 安装cpolar内网穿透工具3. 实现Wagtail公网访问4. 固定的Wagtail公网地址 前言 Wagtail是一个用Python编写的开源CMS&#xff0c;建立在Django Web框架上。Wagtail 是一个基于 Django 的开源内容管理系统&#xf…...

【蓝桥杯/DFS】路径之谜 (Java)

路径之谜小明冒充X星球的骑士&#xff0c;进入了一个奇怪的城堡。 城堡里边什么都没有&#xff0c;只有方形石头铺成的地面。假设城堡地面是 n x n 个方格。【如图1.png】所示。按习俗&#xff0c;骑士要从西北角走到东南角。 可以横向或纵向移动&#xff0c;但不能斜着走&…...

Go语言的内存分配器

1. 内存分配器的历史 Go语言的第一个内存分配器是简单的伙伴分配器。伙伴分配器是一种经典的内存分配器&#xff0c;它将堆内存划分为多个大小相同的块&#xff0c;并使用一种递归的算法来分配和释放内存块。伙伴分配器简单高效&#xff0c;但它存在一个问题&#xff1a;当分配…...

Swift单元测试Quick+Nimble

文章目录 使用QuickNimble1、苹果官方测试框架XCTest的优缺点2、选择QuickNimble的原因&#xff1a;3、QuickNimble使用介绍集成&#xff1a;Quick关键字说明&#xff1a;Nimble中的匹配函数等值判断&#xff1a;使用equal函数是否是同一个对象&#xff1a;使用beIdenticalTo函…...

详解电源动态响应的测试方法及重要性 -纳米软件

电源动态响应测试的重要性 电源动态响应测试是为了检测电源系统在负载变化、输入电压变化情况下的性能表现&#xff0c;包括响应速度、稳定性以及恢复能力等&#xff0c;从而判断电源能否快速、准确地恢复到正常工作状态&#xff0c;为电源的优化设计提供依据。 动态响应能力影…...

计算机网络系统结构-2020期末考试解析

【前言】 不知道为什么计算机网络一门课这么多兄弟&#xff0c;这份看着也像我们的学科&#xff0c;所以也做了。 一&#xff0e; 单选题&#xff08;每题 2 分&#xff0c;共 20 题&#xff0c;合计 40 分&#xff09; 1 、当数据由主机 A 发送到主机 B &#xff0c;不参…...

二叉树的遍历 Java

二叉树的遍历 递归法前序遍历中序遍历后序遍历改进 迭代法前序、后序遍历中序遍历 Java 中 null、NULL、nullptr 区别 public class TreeNode {int val;TreeNode left;TreeNode right;TreeNode() {}TreeNode(int val) { this.val val; }TreeNode(int val, TreeNode left, Tree…...

数据结构之str类

str类 str 是字符串类。str 大概是 Python 中除了int 之外最基本、最常用的数据类型&#xff0c;在Java与其他语言里基本叫做String&#xff0c;其用途广泛&#xff0c;随处可见&#xff0c;但是要记住一点&#xff0c;字符串是不允许修改的。不过&#xff0c;我们仍然可以对其…...

Java电影购票小程序在线选座订票电影

Java电影购票小程序 功能&#xff1a;注册用户可已查看电影场次评价选座订票退票&#xff0c;影院管理员可以排片退款在线卖票和管理演播室等。超级管理员可管理电影排片电影院用户管理等。 演示视频 小程序&#xff1a; https://www.bilibili.com/video/BV11W4y1A7mK/?shar…...

24-1-9 bilibilic++音视频

下午两点面试&#xff0c;面试官迟到了一会&#xff0c;面试官人很好&#xff0c;整体面试经历很不错&#xff0c;但是我人太紧张了&#xff0c;基础知识掌握的深度不够&#xff0c;没有深挖&#xff0c; 是做音视频的底层相关的&#xff0c; 实习要求只要每天打卡够九个小时就…...

备案(三)

首次备案需要多少天 备案初审&#xff1a;您提交初审后&#xff0c;天翼云会在一个工作日内进行审核&#xff0c;并通过短信和邮件形式通知审核结果。 管局审核&#xff1a;各地通管局审核时间不同&#xff0c;一般为1到20个工作日&#xff0c;审核结果将以短信和邮件形式通知…...

Hotspot源码解析-第十九章-ClassLoaderData、符号表、字符串表的初始化

第十九章-ClassLoaderData初始化 讲解本章先从一张图开始 众所周知&#xff0c;Java类的相关信息都是存储在元空间中的&#xff0c;但是是怎么存储的&#xff0c;相信很多读者是不清楚的&#xff0c;这里就不得不涉及到ClassLoaderDataGraph、classLoader、classLoaderData&…...

impala元数据自动刷新

一.操作步骤 进入CM界面 > Hive > 配置 > 搜索 启用数据库中的存储通知(英文界面搜索&#xff1a;Enable Stored Notifications in Database)&#xff0c;并且勾选&#xff0c;注意一定要勾选&#xff0c;配置后面的配置不生效。数据库通知的保留时间默认为2天&#…...

骑砍战团MOD开发(35)-射击精度系统

一.射击精度 和CF等FPS射击类游戏一样,为了模拟实际射击过程中弓箭,子弹等投掷物的射击偏移,故设计精度系统控制不同武器不同兵种的使用武器能力,统称为游戏精度系统. 由于骑砍可以在马上进行射击,故引擎内部也内置了骑射技能点以便控制玩家在骑马过程中射击的能力. 武器精度:通…...

树莓派非常实用的程序-3 vcdbg

vcdbg 是一个应用程序&#xff0c;用于帮助从在ARM上运行的Linux调试VideoCore GPU。它需要以根用户身份运行。此应用程序主要用于Raspberry Pi工程师&#xff0c;尽管有一些命令一般用户可能会发现有用。 sudo vcdbg help 将给出可用命令的列表。 NOTE 仅列出了最终用户使用…...

jmeter分布式服务搭建

目录 一、环境准备 二、 安装包下载 三 、安装jdk 四 、控制机安装 4.1 解压压缩包 4.2 修改 bin/jmeter.properties 4.3 修改 bin/system.properties 五、执行机安装 5.1 解压安装包 5.2 修改 bin/jmeter.properties 5.3 修改 bin/system.properties 5.4 启动执行机 …...

vue中el-radio无法默认选中

页面上不生效&#xff0c;默认什么都不选中 <el-radio-group v-model"queryParams.videoUrlType"><el-radio :label"1">本地上传</el-radio><el-radio :label"2">外部链接</el-radio> </el-radio-group>da…...

分布式I/O应用于智慧停车场的方案介绍

客户案例背景 目前车位检测技术有磁电技术、超声波技术、红外线技术、图像识别车位技术。考虑到例如电磁干扰、信号干扰等的环境因素影响&#xff0c;通常会采用组合使用的方式进行&#xff0c;如采用不同的传感器、应用不同的协议等&#xff0c;以便提高车位检测的准确性和实时…...

node后端+vue前端实现接口请求时携带authorization验证

node后端vue前端实现接口请求时携带authorization验证 我们在写web项目时&#xff0c;后端写好接口&#xff0c;前端想要调用后端接口时&#xff0c;除了登录注册页面&#xff0c;所有的请求都需要携带authorization&#xff0c;这样是为了避免随意通过接口调取数据的现象发生…...

SourceTree管理git

SourceTree管理git...

【数模百科】一篇文章讲清楚灰色预测模型GM(1,1)附python代码

本篇文章摘录自GM(1,1) - 数模百科 &#xff0c;如果想了解更多有关灰色预测模型的信息&#xff0c;请移步 灰色预测模型 - 数模百科 首先&#xff0c;“灰色”这个词在这里不是指颜色&#xff0c;而是形容一种信息状态&#xff0c;介于黑&#xff08;信息全无&#xff09;和白…...

openssl3.2 - 官方demo学习 - mac - hmac-sha512.c

文章目录 openssl3.2 - 官方demo学习 - mac - hmac-sha512.c概述笔记END openssl3.2 - 官方demo学习 - mac - hmac-sha512.c 概述 MAC算法为HMAC, 设置参数(摘要算法为SHA3-512), 用key初始化, 对明文做MAC数据. 笔记 /*! \file hmac-sha512.c \note openssl3.2 - 官方demo…...

pycharm的使用技巧

1.新建文件时,自动生成代码 settings->editor->file and code templates,选择python script ${NAME} 文件名 ${DATE} 日期 2.自动补齐自定义段落 settings->editor->live templates,在右侧点击+号,添加自定义的内容 完成之后,在下方勾选python 3.修改注释的…...