鸿蒙开发案例:七巧板

【1】引言(完整代码在最后面)

本文介绍的拖动七巧板游戏是一个简单的益智游戏,用户可以通过拖动和旋转不同形状的七巧板块来完成拼图任务。整个游戏使用鸿蒙Next框架开发,利用其强大的UI构建能力和数据响应机制,实现了流畅的用户体验。

【2】环境准备

电脑系统:windows 10

开发工具:DevEco Studio NEXT Beta1 Build Version: 5.0.3.806

工程版本:API 12

真机:Mate 60 Pro

语言:ArkTS、ArkUI

【3】关键技术点

1. TangramBlock 类定义 游戏的核心在于TangramBlock类的定义,它封装了每个七巧板块的属性和行为。类中包含了宽度、高度、颜色、初始和当前偏移量、旋转角度等属性,并提供了重置数据的方法。这为后续的数据绑定和UI渲染奠定了基础。

2. 数据绑定与响应式更新 在鸿蒙Next中,使用@ObservedV2和@Trace装饰器可以轻松实现数据的观察和响应式更新。每当TangramBlock实例中的属性发生变化时,UI会自动更新以反映最新的状态。这种机制极大地简化了数据同步的工作,使得开发者可以专注于逻辑实现而无需担心UI更新的问题。

3. UI构建与布局管理 鸿蒙Next提供了丰富的UI组件和布局工具,使得构建复杂的用户界面变得简单。在这个项目中,我们使用了Column、Stack、Polygon等组件来构建七巧板块的布局。通过嵌套这些组件,我们可以灵活地控制每个板块的位置和大小。

4. 手势处理与交互 为了实现拖动和旋转功能,我们使用了PanGesture和rotate方法来处理用户的触摸和手势操作。当用户拖动板块时,通过更新initialOffsetX和initialOffsetY属性,可以实时反映板块的位置变化。同样,通过增加或减少rotationAngle属性,可以实现板块的旋转效果。

5. 动画与过渡 鸿蒙Next内置了丰富的动画和过渡效果,使得用户交互更加自然。在本项目中,我们使用了animateTo方法来平滑地更新板块的状态,从而提升了用户体验。

5.1 旋转动画属性

.rotate({angle: block.rotationAngle,
})

5.2 翻转动画属性

.rotate({x: 0,y: 1,z: 0,angle: block.flipAngle,centerX: block.width / 2, // 中心点X坐标centerY: block.height / 2, // 中心点Y坐标
})

5.3 平移动画属性

.translate({ x: block.initialOffsetX, y: block.initialOffsetY, z: 0 })

【完整代码】

@ObservedV2 // 监听数据变化的装饰器
class TangramBlock { // 定义七巧板类width: number; // 宽度height: number; // 高度points: Array<[number, number]>; // 点坐标数组color: string; // 颜色@Trace initialOffsetX: number; // 初始X偏移量@Trace initialOffsetY: number; // 初始Y偏移量@Trace currentOffsetX: number; // 当前X偏移量@Trace currentOffsetY: number; // 当前Y偏移量@Trace rotationAngle: number; // 旋转角度@Trace flipAngle: number = 0; // 翻转角度,默认为0@Trace rotateValue: number; // 旋转值defaultInitialOffsetX: number; // 默认初始X偏移量defaultInitialOffsetY: number; // 默认初始Y偏移量defaultRotationAngle: number; // 默认旋转角度constructor(color: string, width: number, height: number, initialOffsetX: number, initialOffsetY: number,rotationAngle: number, points: Array<[number, number]>) {this.initialOffsetX = this.currentOffsetX = this.defaultInitialOffsetX = initialOffsetX; // 初始化X偏移量this.initialOffsetY = this.currentOffsetY = this.defaultInitialOffsetY = initialOffsetY; // 初始化Y偏移量this.rotationAngle = this.rotateValue = this.defaultRotationAngle = rotationAngle; // 初始化旋转角度this.color = color; // 设置颜色this.width = width; // 设置宽度this.height = height; // 设置高度this.points = points; // 设置点坐标数组}resetData() { // 重置数据方法this.flipAngle = 0; // 重置翻转角度this.initialOffsetX = this.currentOffsetX = this.defaultInitialOffsetX; // 重置初始X偏移量this.initialOffsetY = this.currentOffsetY = this.defaultInitialOffsetY; // 重置初始Y偏移量this.rotationAngle = this.rotateValue = this.defaultRotationAngle; // 重置旋转角度}
}const baseUnitLength: number = 80; // 基本单位长度@Entry // 入口组件
@Component // 定义组件
export struct Index { // 主组件@State selectedBlockIndex: number = -1; // 当前选中位置@State blocks: TangramBlock[] = [// 七巧板数组// 小直角等腰三角形new TangramBlock("#fed8e5", baseUnitLength, baseUnitLength, -33.58, -58.02, 135,[[0, 0], [baseUnitLength, 0], [0, baseUnitLength]]),new TangramBlock("#0a0bef", baseUnitLength, baseUnitLength, 78.76, 54.15, 45,[[0, 0], [baseUnitLength, 0], [0, baseUnitLength]]),// 中直角等腰三角形new TangramBlock("#ff0d0c", baseUnitLength * Math.sqrt(2), baseUnitLength * Math.sqrt(2), -33.16, -1.43, -90,[[0, 0], [baseUnitLength * Math.sqrt(2), 0], [0, baseUnitLength * Math.sqrt(2)]]),// 大直角等腰三角形new TangramBlock("#ffa60a", baseUnitLength * 2, baseUnitLength * 2, 22.46, -172, -135,[[0, 0], [baseUnitLength * 2, 0], [0, baseUnitLength * 2]]),new TangramBlock("#3da56a", baseUnitLength * 2, baseUnitLength * 2, 135.65, -59.34, -45,[[0, 0], [baseUnitLength * 2, 0], [0, baseUnitLength * 2]]),// 正方形new TangramBlock("#ffff0b", baseUnitLength, baseUnitLength, 23.07, -1.84, -45,[[0, 0], [baseUnitLength, 0], [baseUnitLength, baseUnitLength], [0, baseUnitLength]]),// 平行四边形new TangramBlock("#5e0b9b", baseUnitLength * 2, baseUnitLength, -61.53, -85.97, 45,[[0, 0], [baseUnitLength, 0], [baseUnitLength * 2, baseUnitLength], [baseUnitLength, baseUnitLength]])];build() { // 构建方法Column({ space: 30 }) { // 创建垂直布局Stack() { // 创建堆叠布局ForEach(this.blocks, (block: TangramBlock, index: number) => { // 遍历七巧板数组Stack() { // 创建堆叠布局Polygon({ width: block.width, height: block.height })// 绘制多边形.points(block.points)// 设置多边形顶点坐标.fill(block.color)// 填充颜色.draggable(false)// 长按不可拖动.rotate({ angle: block.rotationAngle }) // 旋转角度}.rotate({// 旋转x: 0,y: 1,z: 0,angle: block.flipAngle,centerX: block.width / 2, // 中心点X坐标centerY: block.height / 2, // 中心点Y坐标}).width(block.width) // 设置宽度.height(block.height) // 设置高度.onTouch(() => { // 触摸事件this.selectedBlockIndex = index; // 设置选中索引}).draggable(false) // 长按不可拖动.translate({ x: block.initialOffsetX, y: block.initialOffsetY, z: 0 }) // 平移.gesture( // 手势操作PanGesture()// 拖动手势.onActionUpdate((event: GestureEvent | undefined) => { // 更新事件if (event) {block.initialOffsetX = block.currentOffsetX + event.offsetX; // 更新X偏移量block.initialOffsetY = block.currentOffsetY + event.offsetY; // 更新Y偏移量}}).onActionEnd((event: GestureEvent | undefined) => { // 结束事件if (event) {block.currentOffsetX = block.initialOffsetX; // 更新当前X偏移量block.currentOffsetY = block.initialOffsetY; // 更新当前Y偏移量}})).zIndex(this.selectedBlockIndex == index ? 1 : 0) // 设置层级.borderWidth(2) // 边框宽度.borderStyle(BorderStyle.Dashed) // 边框样式.borderColor(this.selectedBlockIndex == index ? "#80a8a8a8" : Color.Transparent) // 边框颜色})}.width('100%').height('750lpx') // 设置宽高.backgroundColor("#e4f2f5") // 背景颜色// 旋转角度计数器Column({ space: 5 }) { // 创建垂直布局,设置间距Text(`旋转角度(间隔5)`).fontColor(Color.Black) // 显示旋转角度文本,设置字体颜色Counter() { // 创建计数器组件Text(`${this.selectedBlockIndex != -1 ? this.blocks[this.selectedBlockIndex].rotationAngle :'-'}`)// 显示当前选中七巧板的旋转角度或占位符.fontColor(Color.Black) // 设置字体颜色}.width(300) // 设置计数器宽度.onInc(() => { // 增加按钮的点击事件if (this.selectedBlockIndex != -1) {animateTo({}, () => {this.blocks[this.selectedBlockIndex].rotationAngle += 5; // 增加旋转角度})}}).onDec(() => { // 减少按钮的点击事件if (this.selectedBlockIndex != -1) {animateTo({}, () => {this.blocks[this.selectedBlockIndex].rotationAngle -= 5; // 减少旋转角度})}});}// 旋转角度计数器Column({ space: 5 }) { // 创建垂直布局,设置间距Text(`旋转角度(间隔45)`).fontColor(Color.Black) // 显示旋转角度文本,设置字体颜色Counter() { // 创建计数器组件Text(`${this.selectedBlockIndex != -1 ? this.blocks[this.selectedBlockIndex].rotationAngle :'-'}`)// 显示当前选中七巧板的旋转角度或占位符.fontColor(Color.Black) // 设置字体颜色}.width(300) // 设置计数器宽度.onInc(() => { // 增加按钮的点击事件if (this.selectedBlockIndex != -1) {animateTo({}, () => {this.blocks[this.selectedBlockIndex].rotationAngle += 45; // 增加旋转角度})}}).onDec(() => { // 减少按钮的点击事件if (this.selectedBlockIndex != -1) {animateTo({}, () => {this.blocks[this.selectedBlockIndex].rotationAngle -= 45; // 减少旋转角度})}});}// 翻转按钮Row() { // 创建水平布局Button('向左翻转').onClick(() => { // 左翻转按钮点击事件animateTo({}, () => {if (this.selectedBlockIndex != -1) {this.blocks[this.selectedBlockIndex].flipAngle -= 180; // 减少翻转角度}});});Button('向右翻转').onClick(() => { // 右翻转按钮点击事件animateTo({}, () => {if (this.selectedBlockIndex != -1) {this.blocks[this.selectedBlockIndex].flipAngle += 180; // 增加翻转角度}});});}.width('100%').justifyContent(FlexAlign.SpaceEvenly) // 设置宽度和内容对齐方式// 重置和隐藏边框按钮Row() { // 创建水平布局Button('重置').onClick(() => { // 重置按钮点击事件animateTo({}, () => {for (let i = 0; i < this.blocks.length; i++) {this.blocks[i].resetData(); // 重置七巧板数据}this.selectedBlockIndex = -1; // 重置选中索引});});Button('隐藏边框').onClick(() => { // 隐藏边框按钮点击事件this.selectedBlockIndex = -1; // 重置选中索引});}.width('100%').justifyContent(FlexAlign.SpaceEvenly) // 设置宽度和内容对齐}.width('100%').height('100%')}
}

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

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

相关文章

(61)使用LMS算法估计线性预测器并计算估计误差的MATLAB仿真

文章目录 前言一、仿真说明二、仿真代码三、仿真结果1.LMS自适应滤波器权向量更新曲线2.LMS自适应滤波器算法学习曲线3.期望信号与LMS自适应滤波器输出信号 前言 本文介绍了LMS自适应滤波器对线性预测器系统权系数的估计&#xff0c;进行100次独立实验&#xff0c;计算平均估计…

313页电力集团大数据应用支撑平台技术支撑服务项目技术投标方案

▲关注智慧方案文库&#xff0c;学习9000多份最新解决方案&#xff0c;其中 PPT、WORD超过7000多份 &#xff0c;覆盖智慧城市多数领域的深度知识社区&#xff0c;稳定更新4年&#xff0c;日积月累&#xff0c;更懂行业需求。 313页Word大型电力集团大数据应用支撑平台 技术支…

6款IntelliJ IDEA插件,让Spring和Java开发如虎添翼

文章目录 1、SonarLint2、JRebel for IntelliJ3、SwaggerHub插件4、Lombok插件5、RestfulTool插件6、 Json2Pojo插件7、结论 对于任何Spring Boot开发者来说&#xff0c;两个首要的目标是最大限度地提高工作效率和确保高质量代码。IntelliJ IDEA 是目前最广泛使用的集成开发环境…

标准IO的应用

1、使用这fscanf和fprintf两个函数实现文件的拷贝。 #include<myhead.h> int main(int argc, const char *argv[]) {FILE *fp;if((fpfopen("./1.txt","w"))NULL){perror("fopen");return -1;}int num100;printf("num%d\n",num…

CPU Study - Instructions Fetch

参考来源&#xff1a;《超标量处理器设计》—— 姚永斌 N-Way CPU 取指问题 如果CPU可以在每个周期内同时解码N条指令&#xff0c;则此类CPU为N-Way超标量处理器。 N-Way超标量处理器需要每个周期从I-Cache中至少取得N条指令&#xff0c;这N条指令成为一组Fetch Group。 为了…

蓝桥杯真题——三角回文数(C语言)

问题描述 对于正整数 n, 如果存在正整数 k 使得 n123⋯kk(k1)2n123⋯kk(k1)/2​, 则 n 称为三角数。例如, 66066 是一个三角数, 因为 66066123⋯36366066123⋯363 。 如果一个整数从左到右读出所有数位上的数字, 与从右到左读出所有数位 上的数字是一样的, 则称这个数为回文数…

string模拟实现构造+析构

个人主页&#xff1a;Jason_from_China-CSDN博客 所属栏目&#xff1a;C系统性学习_Jason_from_China的博客-CSDN博客 所属栏目&#xff1a;C知识点的补充_Jason_from_China的博客-CSDN博客 string模拟实现构造 方案1&#xff08;初始化列表的实现&#xff09;&#xff1a; 这…

yolov8涨点系列之Concat模块改进

文章目录 Concat模块修改步骤(1) BiFPN_Concat3模块编辑(2)在__init_.pyconv.py中声明&#xff08;3&#xff09;在task.py中声明yolov8引入BiFPN_Concat3模块yolov8.yamlyolov8.yaml引入C2f_up模块 在YOLOv8中&#xff0c; concat模块主要用于将多个特征图连接在一起。其具体…

基于Spring Boot和Vue的电子商城系统功能设计

基于Spring Boot和Vue的电子商城系统功能设计 该系统是一个基于Spring Boot和Vue框架的电子商城平台&#xff0c;包含前台商城和后台管理系统。系统功能设计包括用户购物体验和管理员管理功能&#xff0c;支持商品的分类展示、收藏、购物车和订单管理等模块。以下是系统功能的简…

【课程总结】day34:多模态大模型之ViT模型、CLIP模型论文阅读理解

前言 在【课程总结】day31&#xff1a;多模态大模型初步了解一文中&#xff0c;我们对多模态大模型的基本原理有了初步了解&#xff0c;本章内容将通过论文阅读理解&#xff0c;更进一步理解多模态大模型中所涉及的 Vit 架构、Transformer在视觉应用的理念以及 Clip图像与文本…

实现数传数据转网口(以太网)和遥控器SBUS信号转串口的功能

为了帮助你实现数传数据转网口&#xff08;以太网&#xff09;和SBUS信号转串口的功能&#xff0c;这里提供一个基本的框架。我们将使用STM32微控制器来完成这些任务。假设你已经具备了STM32的基本开发经验&#xff0c;并且已经安装了相应的开发环境&#xff08;如STM32CubeIDE…

【大数据学习 | kafka高级部分】kafka的快速读写

1. 追加写 根据以上的部分我们发现存储的方式比较有规划是对于后续查询非常便捷的&#xff0c;但是这样存储是不是会更加消耗存储性能呢&#xff1f; 其实kafka的数据存储是追加形式的&#xff0c;也就是数据在存储到文件中的时候是以追加方式拼接到文件末尾的&#xff0c;这…

【超级详细】基于Zynq FPGA对雷龙SD NAND的测试

目录 一、SD NAND特征1.1 SD卡简介1.2 SD卡Block图 二、SD卡样片三、Zynq测试平台搭建3.1 测试流程3.2 SOC搭建 一、SD NAND特征 1.1 SD卡简介 雷龙的SD NAND有很多型号&#xff0c;在测试中使用的是CSNP4GCR01-AMW与CSNP32GCR01-AOW。芯片是基于NAND FLASH和 SD控制器实现的…

[357]基于springboot的中小型制造企业质量管理系统

摘 要 信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突如其来的互联网让传统的信息管理看到了革命性的曙光&#xff0c;因为传统信息管理从时效性&#xff0c;还是安全性&#xff0c;还是可操作性等各个方面来讲&#xff0c;遇到了互联网时代才发现能补上自古…

数据结构:跳表实现(C++)

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》《C》《Linux》《网络》 《redis学习笔记》 文章目录 前言跳表跳表的优化思路skiplist&#xff0c;平衡搜索树&#xff0c;哈希表的对比 实现思路SkiplistNodesearch 搜索add 增加earse 删除 整体…

Rancher的安装

1. 概览 1.1 用户界面优势 Rancher 提供了一个直观的图形用户界面&#xff08;GUI&#xff09;。对于不熟悉 Kubernetes 复杂的命令行操作&#xff08;如使用kubectl&#xff09;的用户来说&#xff0c;通过 Rancher 的界面可以方便地进行资源管理。例如&#xff0c;用户可以在…

文件上传和下载

目录 一、准备工作 二、文件上传 三、文件下载 一、准备工作 如果想使用Spring的文件上传功能&#xff0c;则需要再上下文中配置MultipartResolver前端表单要求&#xff1a;为了能上传文件&#xff0c;必须将表单的method设置为post&#xff0c;并将enctype设置为multipart…

Docker 镜像拉不动?自建 Docker Hub 加速站 解决镜像拉取失败

本文首发于只抄博客&#xff0c;欢迎点击原文链接了解更多内容。 前言 众所周知&#xff0c;6 月份的时候&#xff0c;Docker Hub 的镜像就已经无法正常拉取&#xff0c;那会随手用 Nginx 反代了一下 Docker Hub&#xff0c;建了个自用的镜像站&#xff0c;一直用到了 9 月份&…

真·香!深度体验 zCloud 数据库云管平台 -- DBA日常管理篇

点击蓝字 关注我们 zCloud 作为一款业界领先的数据库云管平台&#xff0c;通过云化自治的部署能力、智能巡检和诊断能力、知识即代码的沉淀能力&#xff0c;为DBA的日常管理工作带来了革新式的简化与优化。经过一周的深度体验&#xff0c;今天笔者与您深入探讨 zCloud 在数据库…

Qt的程序如何打包详细教学

生成Release版的程序 在打包Qt程序时&#xff0c;我们需要将发布程序需要切换为Release版本&#xff08;Debug为调试版本&#xff09;&#xff0c;编译器会对生成的Release版可执行程序进行优化&#xff0c;使生成的可执行程序会更小。 debug版本 debug版本是一种开发过程中的…