【HarmonyOS4学习笔记】《HarmonyOS4+NEXT星河版入门到企业级实战教程》课程学习笔记(十四)

课程地址: 黑马程序员HarmonyOS4+NEXT星河版入门到企业级实战教程,一套精通鸿蒙应用开发

(本篇笔记对应课程第 22 节)

P22《21.ArkUI-实现摇杆功能》

本节我们将小鱼动画案例中的按钮控制改为摇杆控制,用来熟悉和巩固动画效果相关的知识点。

分析实现思路:摇杆控制器包括大圆区域和里面的小圆球,通过用手指控制小圆球移动,来控制小鱼位置变化。

1、我们可以获取手指位置坐标{x,y},并计算出这个坐标值与大圆中心点坐标值的差值,即图中红色横线与竖线,用vx与vy表示。

2、有了这两个值,就可以得到手指与中心点连线与x轴正轴方向的夹角angle,如图中标识出的夹角。我们可以得到手指与中心点连线之间的距离(已知vx,vy,相当于已知直角三角形两条直角边,求斜边长度),这个距离如果超过大圆区域,就取大圆半径,因为小圆球的移动区域需要在大圆范围内,不能移动出大圆。

3、有了这个距离(图中蓝色直角三角形斜边长)和夹角angle,可以得到蓝色直角三角形的两条直角边长,也就是小圆球的移动坐标值。有了这个移动坐标值,我们就可以控制小圆球的移动了。

在这里插入图片描述

4、控制小鱼位置:小鱼移动需要有一个速度值,这个速度值相当于其在某个方向上移动出去的距离,也就是相当于黄色直角三角形的斜边长,有了斜边长和angle角度,可以得到黄色直角三角形的两条直角边长,即小鱼的移动坐标距离。

在这里插入图片描述

摇杆区静态代码:

在这里插入图片描述

给大摇杆添加touch事件:

在这里插入图片描述

事件中的逻辑思路如下几步注释:

在这里插入图片描述

screenX 与 screenY 指的是手指触摸点在整个屏幕中的坐标,而 x 与 y 指的是手指触摸点在当前容器中的坐标。我们需要的是 x 与 y
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

测试效果小圆球拖动效果,发现几个小问题:

首先,拖动小圆球拖不动,只有在大圆区域内拖动才能使小圆球移动,这是因为touch事件仅仅是加在大圆上的。

解决:将加在大圆上的 touch 事件改为加在 大圆与小圆球的外层容器上:

在这里插入图片描述

其次,小圆球的拖动不够圆滑,没有动画效果
解决:用显式动画的方式给小球增加动画效果:

在这里插入图片描述

使用curves库(需要导入)中的动画效果:

在这里插入图片描述

再次,手指松开后小球位置需要还原:这就需要对事件类型做出判断,根据不同事件分别进行处理:手指松开时还原小球位置;手指移动时处理小球跟随效果,即我们写出的1-5步的代码:

在这里插入图片描述

给手指松开小球位置还原增加动画效果:

在这里插入图片描述

到这里就完成了摇杆小球跟随手指移动的效果。

接下来我们来控制小鱼的位置:

在这里插入图片描述

在这里插入图片描述

此时测试发现效果是:只有移动小球时,小鱼位置才随之改变,移动小球停止,小鱼就不动了。效果不够圆滑生动。实现小鱼在手指控制小球过程中持续移动,这就需要开启一个定时器。

要想人眼看到动画效果,最低每秒要24帧。定时器设置为40毫秒时,每秒就是25帧。

在这里插入图片描述

在这里插入图片描述

此时发现小鱼不会随着游动方向改变角度,完善小鱼的角度:

在这里插入图片描述

在这里插入图片描述

实践:

// AnimationPage.ets
import router from '@ohos.router'
import curves from '@ohos.curves'@Styles function btnStyle(){.backgroundColor('rgba(0,0,0,0.2)')
}@Entry
@Component
struct AnimationPage {// 小鱼坐标@State fishX: number = 400@State fishY: number = 180// 小鱼角度@State angle: number = 0// 小鱼图片@State src:Resource = $r('app.media.fish')// 是否开始游戏@State isBegin:boolean = false// 摇杆中心区域坐标private centerX:number = 120private centerY:number = 120// 大、小圆半径private maxRadius:number = 100private radius:number = 20// 摇杆小圆球初始位置@State positionX: number = this.centerX@State positionY: number = this.centerY// 角度正弦和余弦sin:number = 0cos:number = 0// 小鱼移动速度speed:number = 0// 任务idtaskId:number = 1build() {Row() {Column() {Stack(){// 返回按钮Button('返回').position({x:0,y:0}).btnStyle().onClick(()=>{router.back()})// 开始游戏按钮if(!this.isBegin){Button('开始游戏').onClick(()=>{animateTo({duration:1000},()=>{this.isBegin = true})})}else{// 小鱼图片Image(this.src).width('80').position({x: this.fishX - 40, y: this.fishY - 40}).rotate({angle:this.angle, centerX:'50%', centerY:'50%'})// .animation({duration:500, tempo:1}).transition({type:TransitionType.Insert,opacity:0,translate:{x: -200}})}// 操作按钮/*Row(){Button('←').btnStyle().type(ButtonType.Circle).onClick(()=>{animateTo({ duration:500 },()=>{this.src = $r('app.media.fish_left')this.fishX -= 40})})Column({space:20}){Button('↑').btnStyle().type(ButtonType.Circle).onClick(()=>{animateTo({duration:500},()=>{this.fishY -= 40})})Button('↓').btnStyle().type(ButtonType.Circle).onClick(()=>{animateTo({duration:500},()=>{this.fishY += 40})})}Button('→').btnStyle().type(ButtonType.Circle).onClick(()=>{animateTo({ duration:500 },()=>{this.src = $r('app.media.fish')this.fishX += 40})})}.width(120).position({x:10,y:250}).justifyContent(FlexAlign.Center)*/// 摇杆控制Row(){Circle({ width: this.maxRadius * 2, height:this.maxRadius * 2}).fill('#20101010').position({x:this.centerX - this.maxRadius, y:this.centerX - this.maxRadius })Circle({ width: this.radius * 2, height:this.radius * 2})// .fill('#403A3A3A').fill('#d3601010').position({x:this.positionX - this.radius, y:this.positionY - this.radius })}.width(240).height(240).position({x:0, y:120}).onTouch(this.handleTouchEvent.bind(this))}.width('100%').height('100%')}.width('100%').height('100%')}.width('100%').height('100%').backgroundImage($r('app.media.fish_bg'),ImageRepeat.NoRepeat).backgroundImageSize(ImageSize.Cover).backgroundImagePosition(Alignment.Bottom)}handleTouchEvent = (event:TouchEvent)=>{switch (event.type){case TouchType.Up:// 还原小球位置animateTo({ curve:curves.springMotion() },()=>{this.positionX = this.centerXthis.positionY = this.centerY})// 还原小鱼速度this.speed = 0// 还原小鱼角度this.angle = 0// 取消定时任务clearInterval(this.taskId)break;case TouchType.Down:this.taskId = setInterval(()=>{this.fishX += this.speed * this.costhis.fishY += this.speed * this.sin},40)break;case TouchType.Move:// 1、获取手指位置坐标let x = event.touches[0].xlet y = event.touches[0].y// 2、计算手指与中心点的坐标差值let vx = x - this.centerXlet vy = y - this.centerY// 3、计算手指与中心点连线与x轴正半轴的夹角,单位是弧度let angle = Math.atan2(vy,vx)// 4、计算手指与中心点的距离let distance = this.getDistance(vx,vy)// 5、计算摇杆小球的坐标this.sin = Math.sin(angle)this.cos = Math.cos(angle)animateTo({ curve:curves.responsiveSpringMotion() },()=>{// 修改摇杆小球的坐标this.positionX = this.centerX + distance * this.costhis.positionY = this.centerY + distance * this.sin// 修改小鱼的坐标this.speed = 5/*this.fishX += this.speed * this.costhis.fishY += this.speed * this.sin*/// 小鱼向右游if(Math.abs(angle * 2) < Math.PI){this.src = $r('app.media.fish')}else{  // 小鱼向左游this.src = $r('app.media.fish_left')angle = angle < 0 ? angle + Math.PI : angle - Math.PI  // todo 这句不太懂}// 修改小鱼的角度this.angle = angle * 180 / Math.PI})break;}}getDistance = (x:number,y:number)=>{let d = Math.sqrt(x*x + y*y)return Math.min(d, this.maxRadius)}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/30890.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【多模态论文】CLIP(Contrastive Language-Image Pre-training)

论文&#xff1a;Learning Transferable Visual Models From Natural Language Supervision 链接&#xff1a;https://arxiv.org/abs/2103.00020 摘要 问题&#xff1a; 对预定的类别进行预测&#xff0c;这种有监督的训练形式受限于额外标记数据 。如何利用图像的原始文本来获…

图像数字化基础

一、像素 1、获取图像指定位置的像素 import cv2 image cv2.imread("E:\\images\\2.png") px image[291,218] print("坐标(291,218)上的像素的BGR值是&#xff1a;",px) &#xff08;1&#xff09;RGB色彩空间 R通道&#xff1a;红色通道 G通道&…

RH850---注意问题积累--1

硬件规格(引脚分配&#xff0c;内存映射&#xff0c;外设功能规格、电气特性、时序图)和操作说明 注意:有关使用的详细信息&#xff0c;请参阅应用说明 ---------外围函数。。。 1:存储指令完成与后续同步指令的一代 当控制寄存器被存储指令更新时&#xff0c;从存储的执行开始…

南京邮电大学计算机网络实验二(网络路由器配置RIP协议)

文章目录 一、 实验目的和要求二、 实验环境(实验设备)三、 实验步骤四、实验小结&#xff08;包括问题和解决方法、心得体会、意见与建议等&#xff09;五、报告资源 一、 实验目的和要求 掌握思科路由器的运行过程&#xff0c;掌握思科路由器的硬件连线与接口&#xff0c;掌…

VBA学习(13):获取多层文件夹内文件名并建立超链接

代码使用了FileSystemObject对象和递归的方法实现文件夹和文件的遍历功能。分别将文件夹名称和文件名提取在表格的A/B列&#xff0c;并对文件名创建了超链接。 示例代码如下&#xff1a; Sub AutoAddLink()Dim strFldPath As StringWith Application.FileDialog(msoFileDialog…

如何下载DVS Gesture数据集?解决tonic.datasets.DVSGesture错误HTTP Error 403: Forbidden

1 问题 DVSGesture数据集是一个专注于动态视觉传感&#xff08;Dynamic Vision Sensor, DVS&#xff09;技术的数据集&#xff0c;它包含了基于事件的图像记录&#xff0c;用于手势识别任务。DVSGesture数据集由一系列动态图像组成&#xff0c;这些图像是通过动态视觉传感器捕…

抖音矩阵系统搭建,AI剪辑短视频,一键管理矩阵账号

目录 前言&#xff1a; 一、抖音矩阵系统有哪些功能&#xff1f; 1.AI智能文案 2.多平台账号授权 3.多种剪辑模式 4. 矩阵一键发布&#xff0c;智能发布 5.抖音爆店码功能 6.私信实时互动 7.去水印及外链 二、抖音矩阵系统可以解决哪些问题&#xff1f; 总结&#xff…

理解HTTP请求格式

HTTP概念 HTTP全称HyperTextTransfer Protocol(超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议&#xff1b;HTTP是一个客户端&#xff08;用户&#xff09;和服务端&#xff08;网站&#xff09;之间请求和响应的标准。 HTTP 协议是以 ASCII 码传输&…

Gobject tutorial 八

The GObject base class Object memory management Gobject的内存管理相关的API很复杂&#xff0c;但其目标是提供一个基于引用计数的灵活的内存管理模式。 下面我们来介绍一下&#xff0c;与管理引用计数相关的函数。 Reference Count 函数g_object_ref和g_object_unref的…

怎么将几段音频合并在一起,试试这几个音频拼接小妙招

怎么将多个音频合并在一起呢&#xff1f;音频是我们日常工作生活中常见的文件&#xff0c;音频与我们息息相关&#xff0c;无论你是音乐爱好者&#xff0c;还是喜欢记录生活中的声音&#xff0c;都离不开音频。因此我们会遇到关于很多音频剪辑的难题&#xff0c;就像今天小编给…

usb摄像头应用编程

作者简介&#xff1a; 一个平凡而乐于分享的小比特&#xff0c;中南民族大学通信工程专业研究生在读&#xff0c;研究方向无线联邦学习 擅长领域&#xff1a;驱动开发&#xff0c;嵌入式软件开发&#xff0c;BSP开发 作者主页&#xff1a;一个平凡而乐于分享的小比特的个人主页…

conda install xformers -c xformers/label/dev 的安装问题

在StableSR项目框架中&#xff0c;需要执行 conda install xformers -c xformers/label/dev 但是报错&#xff0c;错误显示&#xff0c;版本不匹配&#xff0c;如下所示&#xff1a; 我改用pip来安装&#xff0c;好像就不报错了&#xff1a; pip install xformers

javaWeb项目-ssm+vue企业台账管理平台功能介绍

本项目源码&#xff1a;javaweb项目ssm-vue企业台账管理平台源码-说明文档资源-CSDN文库 项目关键技术 开发工具&#xff1a;IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架&#xff1a;ssm、Springboot 前端&#xff1a;Vue、ElementUI 关键技术&#xff1a;springboo…

vue项目——前端CryptoJS加密、解密

1、vue项目需要安装CryptoJS安装包 npm install crypto-js 2、在项目中引入CryptoJS import CryptoJS from crypto-js 3、使用&#xff0c;代码如下 // 此处key为16进制let key jiajiajiajiajiajiajiajia;console.log(密钥&#xff1a;, key);// key格式化处理key Crypt…

【前端开发工具】VS Code安装和使用

文章目录 一、前言二、下载三、安装四、配置五、使用5.1 导入项目5.2 本地运行项目5.3 修改界面文案&#xff0c;验证效果5.4 添加日志打印5.5 代码调试5.6 代码提交到Git仓库 六、总结 一、前言 本文介绍一下在前端vue项目中&#xff0c;VS Code的安装和配置。 什么是VS Code…

【干货分享】25地学考研推免夏令营汇总表

​ 25考研学子们&#xff0c;考研准备要赶早。 小编给大家整合准备了25地信考研夏令营时间信息表&#xff0c;需要的宝子收藏起来。 ​ 话不多说&#xff0c;需要的小伙伴直接评论区留言 25地信考研择校信息表&#xff1a;

IT入门知识第一部分《IT基础知识》(1/10)

目录 IT入门知识第一部分《IT基础知识》&#xff08;1/10&#xff09; 1.引言 2.第一部分&#xff1a;IT基础知识 2.1 计算机硬件 CPU&#xff1a;计算机的心脏 内存&#xff1a;数据的临时居所 存储设备&#xff1a;数据的长期仓库 输入输出设备&#xff1a;与计算机的…

[Mysql] 的基础知识和sql 语句.教你速成(上)——逻辑清晰,涵盖完整

目录 前言 上篇的内容概况 下篇的内容概况 数据库的分类 关系型数据库 常见的关系型数据库系统 非关系型数据库 1. 键值对数据库&#xff08;Key-Value Stores&#xff09; 特点&#xff1a; 常见的键值对数据库&#xff1a; 2. 文档数据库&#xff08;Document Store…

【React】Axios请求头注入token

业务背景: Token作为用户的数据标识&#xff0c;在接口层面起到了接口权限控制的作用&#xff0c;也就是说后端有很多接口都需要通过查看当前请求头信息中是否含有token数据&#xff0c;来决定是否正常返回数据 // 添加请求拦截器 request.interceptors.request.use(config …

填坑-celery正常启动后能收到任务但不执行任务的解决办法

场景 Flask开发中用celery 6正常启动后能收到任务但不执行任务的解决办法&#xff0c;也没有错误提示…… INFO/MainProcess] Task app.add_together[ce406ed8-71b3-49e6-8556-f44bfe66549c] received [2024-06-20 19:38:10,632: INFO/SpawnPoolWorker-36] child process 2244…