鸿蒙开发案例:七巧板

【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.rhkb.cn/news/465765.html

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

相关文章

C++_STL_xx_番外01_关于STL的总结(常见容器的总结;关联式容器分类及特点;二叉树、二叉搜索树、AVL树(平衡二叉搜索树)、B树、红黑树)

文章目录 1. 常用容器总结2. 关联式容器分类3. 二叉树、二叉搜索树、AVL树、B树、红黑树 1. 常用容器总结 针对常用容器的一些总结&#xff1a; 2. 关联式容器分类 关联式容器分为两大类&#xff1a; 基于红黑树的set和map&#xff1b;基于hash表的unorder_set和unorder_ma…

Django目录结构最佳实践

Django项目目录结构 项目目录结构配置文件引用修改创建自定义子应用方法修改自定义注册目录从apps目录开始 项目目录结构 └── backend # 后端项目目录&#xff08;项目名称&#xff09;├── __init__.py├── logs # 项目日志目录├── manage.py #…

AnytimeCL:难度加大,支持任意持续学习场景的新方案 | ECCV‘24

来源&#xff1a;晓飞的算法工程笔记 公众号&#xff0c;转载请注明出处 论文: Anytime Continual Learning for Open Vocabulary Classification 论文地址&#xff1a;https://arxiv.org/abs/2409.08518论文代码&#xff1a;https://github.com/jessemelpolio/AnytimeCL 创新…

2020年美国总统大选数据分析与模型预测

数据集取自&#xff1a;2020年&#x1f1fa;&#x1f1f8;&#x1f1fa;&#x1f1f8;美国大选数据集 - Heywhale.com 前言 对2020年美国总统大选数据的深入分析&#xff0c;提供各州和县层面的投票情况及选民行为的可视化展示。数据预处理阶段将涉及对异常值的处理&#xff0…

工业以太网PLC无线网桥,解决用户布线难题!

工业以太网无线网桥 功能概述 本产品是工业以太网(Profinet、EtherNet/IP、ModbusTCP等)转无线设备,成对使用(一对一),出厂前已经配对好,用户不需要再配对,即插即用。适用于用户布线不方便的场景。使用方式简单,只需要把拨码开关设置好并上电即可工作,无需进行其它设置。支持P…

Android13 系统/用户证书安装相关分析总结(三) 增加安装系统证书的接口遇到的问题和坑

一、前言 接上回说到&#xff0c;修改了程序&#xff0c;增加了接口&#xff0c;却不知道有没有什么问题&#xff0c;于是心怀忐忑等了几天。果然过了几天&#xff0c;应用那边的小伙伴报过来了问题。用户证书安装没有问题&#xff0c;系统证书(新增的接口)还是出现了问题。调…

AUTOSAR CP NVRAM Manager规范导读

一、NVRAM Manager功能概述 NVRAM Manager是AUTOSAR(AUTomotive Open System ARchitecture)框架中的一个模块,负责管理非易失性随机访问存储器(NVRAM)。它提供了一组服务和API,用于在汽车环境中存储、维护和恢复NV数据。以下是NVRAM Manager的一些关键功能: 数据存储和…

kelp protocol

道阻且长,行而不辍,未来可期 有很长一段时间我都在互联网到处拾金,but,东拼西凑的,总感觉不踏实,最近在老老实实的看官方文档 & 阅读白皮书 &看合约,挑拣一些重要的部分配上官方的证据,和过路公主or王子分享一下,愿我们早日追赶上公司里那些可望不可及大佬们。…

LeetCode25:K个一组翻转链表

原题地址&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#xff0c;那…

k8s图形化显示(KRM)

在master节点 kubectl get po -n kube-system 这个命令会列出 kube-system 命名空间中的所有 Pod 的状态和相关信息&#xff0c;比如名称、状态、重启次数等。 systemctl status kubelet #查看kubelet状态 yum install git #下载git命令 git clone https://gitee.com/duk…

Github 2024-11-07 Go开源项目日报 Top10

根据Github Trendings的统计,今日(2024-11-07统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Go项目10HTML项目1Kubernetes: 容器化应用程序管理系统 创建周期:3618 天开发语言:Go协议类型:Apache License 2.0Star数量:106913 个Fork数…

HTML 标签属性——<a>、<img>、<form>、<input>、<table> 标签属性详解

文章目录 1. `<a>`元素属性hreftargetname2. `<img>`元素属性srcaltwidth 和 height3. `<form>`元素属性actionmethodenctype4. `<input>`元素属性typevaluenamereadonly5. `<table>`元素属性cellpaddingcellspacing小结HTML元素除了可以使用全局…

制造业仓储信息化总体规划方案

文件是一份关于制造业仓储信息化的总体规划方案&#xff0c;主要内容包括项目背景、现状调研、项目目标、建设思路、业务蓝图设计方案、系统设计方案以及场景展示等。以下是对PPT内容的分析和总结&#xff1a; 1. 项目背景 目标&#xff1a;通过物流执行系统&#xff08;LES&a…

Ubuntu使用Qt虚拟键盘,支持中英文切换

前言 ​最近领导给了个需求&#xff0c;希望将web嵌入到客户端里面&#xff0c;做一个客户端外壳&#xff0c;可以控制程序的启动、停止、重启&#xff0c;并且可以调出键盘在触摸屏上使用(我们的程序虽然是BS架构&#xff0c;但程序还是运行在本地工控机上的)&#xff0c;我研…

python爬取旅游攻略(1)

参考网址&#xff1a; https://blog.csdn.net/m0_61981943/article/details/131262987 导入相关库&#xff0c;用get请求方式请求网页方式&#xff1a; import requests import parsel import csv import time import random url fhttps://travel.qunar.com/travelbook/list.…

基于单片机的农业自动灌溉系统

本设计基于单片机的农业自动灌溉系统&#xff0c;以STM32F103C8T6单片机为控制核心&#xff0c;采用电容式土壤传感器来测量土壤湿度&#xff0c;DHT11温湿度检测模块来测量环境温湿度&#xff0c;OLED屏幕来显示实时时间、Wi-Fi连接状态、环境温湿度、土壤湿度情况以及灌溉情况…

安全工程师入侵加密货币交易所获罪

一名高级安全工程师被判犯有对去中心化加密货币交易所的多次攻击罪&#xff0c;在此过程中窃取了超过 1200 万美元的加密货币。 沙克布艾哈迈德&#xff08;Shakeeb Ahmed&#xff09;被判刑&#xff0c;美国检察官达米安威廉姆斯&#xff08;Damian Williams&#xff09;称其…

Istio Gateway发布服务

1. Istio Gateway发布服务 在集群中部署一个 tomcat 应用程序。然后将部署一个 Gateway 资源和一个与 Gateway 绑定的 VirtualService&#xff0c;以便在外部 IP 地址上公开该应用程序。 1.1 部署 Gateway 资源 vim ingressgateway.yaml --- apiVersion: networking.istio.…

Linux云计算 |【第五阶段】CLOUD-DAY9

主要内容&#xff1a; Metrics资源利用率监控、存储卷管理&#xff08;临时卷ConfitMap、EmptyDir、持久卷HostPath、NFS(PV/PVC)&#xff09; 一、Metrics介绍 metrics是一个监控系统资源使用的插件&#xff0c;可以监控Node节点上的CPU、内存的使用率&#xff0c;或Pod对资…

Java 异常处理的最佳实践

在 Java 开发中&#xff0c;异常处理是一个非常重要的环节。良好的异常处理实践可以提高代码的健壮性、可读性和可维护性。本文将介绍 20 个异常处理的最佳实践&#xff0c;帮助你在实际开发中避免常见的陷阱。 1. 尽量不要捕获 RuntimeException 阿里出品的 Java 开发手册上…