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

本文主要是介绍【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)}
}

这篇关于【HarmonyOS4学习笔记】《HarmonyOS4+NEXT星河版入门到企业级实战教程》课程学习笔记(十四)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1079467

相关文章

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

MyBatis分页查询实战案例完整流程

《MyBatis分页查询实战案例完整流程》MyBatis是一个强大的Java持久层框架,支持自定义SQL和高级映射,本案例以员工工资信息管理为例,详细讲解如何在IDEA中使用MyBatis结合Page... 目录1. MyBATis框架简介2. 分页查询原理与应用场景2.1 分页查询的基本原理2.1.1 分

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

Three.js构建一个 3D 商品展示空间完整实战项目

《Three.js构建一个3D商品展示空间完整实战项目》Three.js是一个强大的JavaScript库,专用于在Web浏览器中创建3D图形,:本文主要介绍Three.js构建一个3D商品展... 目录引言项目核心技术1. 项目架构与资源组织2. 多模型切换、交互热点绑定3. 移动端适配与帧率优化4. 可

从入门到精通详解Python虚拟环境完全指南

《从入门到精通详解Python虚拟环境完全指南》Python虚拟环境是一个独立的Python运行环境,它允许你为不同的项目创建隔离的Python环境,下面小编就来和大家详细介绍一下吧... 目录什么是python虚拟环境一、使用venv创建和管理虚拟环境1.1 创建虚拟环境1.2 激活虚拟环境1.3 验证虚

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

基于C#实现PDF转图片的详细教程

《基于C#实现PDF转图片的详细教程》在数字化办公场景中,PDF文件的可视化处理需求日益增长,本文将围绕Spire.PDFfor.NET这一工具,详解如何通过C#将PDF转换为JPG、PNG等主流图片... 目录引言一、组件部署二、快速入门:PDF 转图片的核心 C# 代码三、分辨率设置 - 清晰度的决定因

Maven中生命周期深度解析与实战指南

《Maven中生命周期深度解析与实战指南》这篇文章主要为大家详细介绍了Maven生命周期实战指南,包含核心概念、阶段详解、SpringBoot特化场景及企业级实践建议,希望对大家有一定的帮助... 目录一、Maven 生命周期哲学二、default生命周期核心阶段详解(高频使用)三、clean生命周期核心阶

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模