鸿蒙小案例-你画我猜

鸿蒙小案例-你画我猜

1.准备组件(组件布局)
2.实现跟随鼠标画笔画出图案功能
3.实现复制上面的画笔的图案功能
4.其他小功能

1.组件的准备

画布的组件官方给的API是Canvas,需要传递一个参数CanvasRenderingContext2D
在这里插入图片描述
直接搜索API 使用官方案例

  private settings: RenderingContextSettings = new RenderingContextSettings(true)private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)Canvas(this.context).width('100%').height('100%').backgroundColor('#ffff00').onReady(() => {this.context.fillRect(0, 30, 100, 100)})}.width('100%').height('100%')

因为我们参数描述到

不支持多个Canvas共用一个CanvasRenderingContext2D对象

所以,结合我们的显示区域,基础代码精简为

@Entry
@Preview
@Component
struct Nihuawocai2 {private context01: CanvasRenderingContext2D = new CanvasRenderingContext2D(new RenderingContextSettings(true))private context02: CanvasRenderingContext2D = new CanvasRenderingContext2D(new RenderingContextSettings(true))/*** 1.准备组件(画布布局)* 2.实现跟随鼠标画笔画出图案* 3.实现复制上面的画笔的图案* 4.其他小功能*/build() {Row() {Column() {//自己绘画的区域Row(){Canvas(this.context01).width('100%').height('100%').backgroundColor(Color.White).onReady(() => {//this.context01.fillRect(0, 30, 100, 100)})}.height('40%').border({ width: { bottom:5 },color:Color.Red })//复制绘画的区域Row(){Canvas(this.context02).width('100%').height('100%').backgroundColor(Color.Grey).onReady(() => {//this.context02.fillRect(0, 30, 100, 100)})}.height('40%')//功能区Row(){Button("清屏").onClick(() =>{})}.height('20%')}.width('100%')}.height('100%')}
}

实现效果:
在这里插入图片描述

2.实现跟随鼠标画笔画出图案

画笔呢肯定是需要用到触摸事件,API如下
在这里插入图片描述
所以Canvas增加onTouch事件

 Canvas(this.context01).width('100%').height('100%').backgroundColor(Color.White).onTouch((event: TouchEvent) =>{})

当触摸事件是按下时,开始绘画
在这里插入图片描述
在这里插入图片描述
所以onTouch增加代码

.onTouch((event: TouchEvent) =>{//按下时触发,开始绘画if (event.type === TouchType.Down){AlertDialog.show({message:'按下手指'})}//抬起时触发  结束绘画if (event.type === TouchType.Up){AlertDialog.show({message:'抬起手指'})}//移动时触发  正在绘画if (event.type === TouchType.Move){AlertDialog.show({message:'移动手指'})}})

预览器测试一下,发现 移动手指会一直显示,说明这个触发是没问题的

接下来首先理一下绘画的思路

按下时,准备绘画,从按下的坐标点开始

移动时,正在绘画,随着移动的轨迹,不停记录坐标点,链接上一个坐标点到新坐标点

抬起时,结束绘画,记录当前坐标点为结束点

可能会有多次按下,抬起的操作

所以,我们需要增加一个坐标类,再给一个是否起始点的布尔值

//坐标对象
class zbClass{x:number = 0y:number = 0//按下时记录true,移动时不记录,抬起时记录falseisStart?:boolean = false
}

增加常量:

是否开始绘画,用来区分多次按下的操作

坐标集合,用来记录绘画轨迹坐标点

//是否开始绘画
isDraw:boolean = false
//坐标点 集合
zbList: zbClass[] = [] 

按下时,记录当前坐标,并增加当前坐标到坐标集合中

//按下时触发,开始绘画
if (event.type === TouchType.Down)
{this.isDraw = truethis.context01X  = event.touches[0].xthis.context01Y  = event.touches[0].ythis.zbList.push({x:this.context01X,y:this.context01Y,isStart:true})//开始绘画this.context01.beginPath()
}

开始绘画,参考CanvasRenderingContext2D API官方案例,既将画笔从一个点连接到另一个点,然后不停循环
在这里插入图片描述
将绘画写成一个方法,直接去调用

//移动时触发  正在绘画
if (event.type === TouchType.Move)
{if (this.isDraw){//绘画中this.drawIng(event.touches[0].x, event.touches[0].y)}
}

drawIng方法

//绘画过程drawIng(x: number, y: number){//先移动画笔到起始点this.context01.moveTo(this.context01X,this.context01Y)//设置绘画边框宽度this.context01.lineWidth = 5//将画笔从上一个坐标 链接到 手指移动到的新坐标this.context01.lineTo(x,y)//更新常量坐标点为手指移动坐标点,随着手指移动,形成循环this.context01X = xthis.context01Y = y//因为有复制操作,所以,需要保存坐标点this.zbList.push({x:x,y:y})this.context01.stroke()}

抬起手指操作

//抬起时触发  结束绘画
if (event.type === TouchType.Up)
{//当前按下手指周期,绘画结束this.isDraw = false//记录当前周期的结束坐标this.zbList.push({x: event.touches[0].x,y: event.touches[0].y,isStart:false})this.context01.closePath()
}

此时通过预览器测试一下,基本功能已经实现,而且抬起再按下也能继续绘画了

3.实现复制上面的画笔的图案

复制动作可以在全部绘画完后,统一复制,也可以在绘画的同时延迟复制

事后统一复制也就是将集合中的点全部连一遍,比较简单,所以我们边画边复制,在抬起一次手指时开始复制
增加常量:

 //复制画,坐标点context02X: number = 0context02Y: number = 0//定时器,用来循环timer: number = -1

增加一个复制方法

//复制动作
cpDraw()
{this.context02.lineWidth = 5this.timer = setInterval(() =>{if (this.zbList.length === 0){clearInterval(this.timer)this.timer = -1return}let p = this.zbList.shift()if (p.isStart){this.context02.closePath()this.context02.beginPath()this.context02X = p.xthis.context02Y = p.y} else{//移动画笔this.context02.moveTo(this.context02X, this.context02Y)//链接点this.context02.lineTo(p.x, p.y)//更新点this.context02X = p.xthis.context02Y = p.ythis.context02.stroke()}}, 100)
}

测试功能,一切OK

4.其他小功能

清理屏幕
将两个画布的坐标点全部都设置为初始点

Button("清屏").onClick(() =>{this.context01.clearRect(0, 0, 360, 300)this.context02.clearRect(0, 0, 360, 300)this.zbList = []})

完整代码

@Entry
@Preview
@Component
struct Nihuawocai2 {private context01: CanvasRenderingContext2D = new CanvasRenderingContext2D(new RenderingContextSettings(true))private context02: CanvasRenderingContext2D = new CanvasRenderingContext2D(new RenderingContextSettings(true))//第一个画布的坐标信息context01X:number = 0context01Y:number = 0//是否开始绘画isDraw:boolean = false//坐标点 集合zbList: zbClass[] = []//下方绘画坐标点context02X: number = 0context02Y: number = 0//定时器,用来循环timer: number = -1//绘画过程drawIng(x: number, y: number){//先移动画笔到起始点this.context01.moveTo(this.context01X,this.context01Y)//将画笔从上一个坐标 链接到 手指移动到的新坐标this.context01.lineTo(x,y)//更新常量坐标点为手指移动坐标点,随着手指移动,形成循环this.context01X = xthis.context01Y = y//因为有复制操作,所以,需要保存坐标点this.zbList.push({x:x,y:y})this.context01.stroke()}//复制动作cpDraw(){this.timer = setInterval(() =>{if (this.zbList.length === 0){clearInterval(this.timer)this.timer = -1return}let p = this.zbList.shift()if (p.isStart){this.context02.closePath()this.context02.beginPath()this.context02X = p.xthis.context02Y = p.y} else{//移动画笔this.context02.moveTo(this.context02X, this.context02Y)//链接点this.context02.lineTo(p.x, p.y)//更新点this.context02X = p.xthis.context02Y = p.ythis.context02.stroke()}}, 100)}/*** 1.准备组件(画布布局)* 2.实现跟随鼠标画笔画出图案* 3.实现复制上面的画笔的图案* 4.其他小功能*/build() {Row() {Column() {//自己绘画的区域Row(){Canvas(this.context01).width('100%').height('100%').backgroundColor(Color.White).onTouch((event: TouchEvent) =>{//按下时触发,开始绘画if (event.type === TouchType.Down){//当前按下手指周期,绘画开始this.isDraw = truethis.context01X  = event.touches[0].xthis.context01Y  = event.touches[0].ythis.zbList.push({x:this.context01X,y:this.context01Y,isStart:true})//开始绘画this.context01.beginPath()}//抬起时触发  结束绘画if (event.type === TouchType.Up){//当前按下手指周期,绘画结束this.isDraw = falsethis.zbList.push({x: event.touches[0].x,y: event.touches[0].y,isStart:false})this.context01.closePath()this.cpDraw()}//移动时触发  正在绘画if (event.type === TouchType.Move){if (this.isDraw){//绘画中this.drawIng(event.touches[0].x, event.touches[0].y)}}}).onReady(() => {//设置绘画边框宽度this.context01.lineWidth = 5})}.height('40%').border({ width: { bottom:5 },color:Color.Red })//复制绘画的区域Row(){Canvas(this.context02).width('100%').height('100%').backgroundColor(Color.Grey).onReady(() => {//设置绘画边框宽度this.context02.lineWidth = 5})}.height('40%')//功能区Row(){Button("清屏").onClick(() =>{this.context01.clearRect(0, 0, 360, 300)this.context02.clearRect(0, 0, 360, 300)this.zbList = []})}.height('20%')}.width('100%')}.height('100%')}
}//坐标对象
class zbClass{x:number = 0y:number = 0//按下时记录true,移动时不记录,抬起时记录falseisStart?:boolean = false
}

使用模拟器测试功能OK
模拟器效果
在这里插入图片描述
— end

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

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

相关文章

L2-1 点赞狂魔——pta(题解)

微博上有个“点赞”功能,你可以为你喜欢的博文点个赞表示支持。每篇博文都有一些刻画其特性的标签,而你点赞的博文的类型,也间接刻画了你的特性。然而有这么一种人,他们会通过给自己看到的一切内容点赞来狂刷存在感,这…

【蓝桥杯Python】试题 算法训练 藏匿的刺客

资源限制 内存限制:256.0MB C/C时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s 问题描述 强大的kAc建立了强大的帝国,但人民深受其学霸及23文化的压迫,于是勇敢的鹏决心反抗。   kAc帝国防守…

C语言——求 1+12+123+……前 n 项之和,其中n 是从键盘输入的一个数字(1~9)。

一、问题 求 112123……前 n 项之和&#xff0c;其中n 是从键盘输入的一个数字&#xff08;1~9&#xff09; 二、解答 #include <stdio.h>int main() {int n, i, term 0, sum 0;printf("请输入一个数字(1~9): ");scanf("%d", &n);if (n <…

书生谱语-基于 InternLM 和 LangChain 搭建知识库

大语言模型与外挂知识库&#xff08;RAG&#xff09;的优缺点 RAG方案构建与优化 作业 在创建web_demo时&#xff0c;需要根据教程将服务器端口映射到本地端口&#xff0c;另外需要将链接的demo从服务器中复制出来&#xff0c;不要直接从服务器打开demo页面&#xff0c;不然会…

分布式事务详解

概述 随着互联网的发展&#xff0c;软件系统由原来的单体应用转变为分布式应用。分布式系统把一个单体应用拆分为可独立部署的多个服务&#xff0c;因此需要服务与服务之间远程协作才能完成事务操作。这种分布式系统下不同服务之间通过远程协作完成的事务称之为分布式事务&…

c# 拼音 帮助类

public class PinYinHelper { #region 获取汉字对应的拼音 /// <summary> /// 获取汉字对应的拼音 /// </summary> /// <param name"str"></param> /// <returns></returns> …

JavaScript中有哪些不同的数据类型

在 JavaScript 中&#xff0c;数据类型是一种用来表示数据的分类&#xff0c;它决定了我们可以对这个数据类型执行哪些操作。在 JavaScript 中有以下几种不同的数据类型&#xff1a; 基本数据类型 字符串 (String)&#xff1a;表示一组字符&#xff0c;可以使用引号&#xff08…

ElasticSearch级查询Query DSL上

目录 ES高级查询Query DSL match_all 返回源数据_source 返回指定条数size 分页查询from&size 指定字段排序sort 术语级别查询 Term query术语查询 Terms Query多术语查询 exists query ids query range query范围查询 prefix query前缀查询 wildcard query通…

CVE-2022-25487 漏洞复现

漏洞描述&#xff1a;Atom CMS 2.0版本存在远程代码执行漏洞&#xff0c;该漏洞源于/admin/uploads.php 未能正确过滤构造代码段的特殊元素。攻击者可利用该漏洞导致任意代码执行。 其实这就是一个文件上传漏洞罢了。。。。 打开之后&#xff0c;/home路由是个空白 信息搜集&…

第十六章 以编程方式使用 SQL 网关 - %SQLGatewayConnection 方法和属性

文章目录 第十六章 以编程方式使用 SQL 网关 - %SQLGatewayConnection 方法和属性GetOneRow()GetParameter()GetUV()Password propertySetConnectOption()SetParameter()SQL 代码属性UnloadDLL()用户属性 第十六章 以编程方式使用 SQL 网关 - %SQLGatewayConnection 方法和属性…

controller-manager学习三部曲之三:deployment的controller启动分析

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 《controller-manager学习三部曲》完整链接 通过脚本文件寻找程序入口源码学习deployment的controller启动分析 本篇概览 本文是《controller-manager学习三…

STM32定时器按键扫描检测(短按)并执行其他内容的源码

文章目录 main.c #include "stm32f10x.h" // Device header #include "Key.h" #include "LED.h" #include "Timer.h"int main(void) {Timer_Init();//1msLED_Init();Key_Init();while(1){switch(KeyFlag)//按键短按&…

深入了解JavaScript混淆工具:jsjiami.v6

JavaScript混淆工具在前端开发中发挥着重要的作用&#xff0c;帮助开发者保护源代码&#xff0c;减少代码被轻易破解的风险。其中&#xff0c;jsjiami.v6 是一款备受开发者关注的混淆工具之一。本文将深入介绍jsjiami.v6的基本原理和使用方法&#xff0c;并通过案例代码演示其效…

0时区格林威治时间转换手机当地时间-Android(2023-11-01T12:59:10.420987)

假设传入的是2023-11-01T12:59:10.420987这样的格式 要将格式为2023-11-01T12:59:10.420987的UTC时间字符串转换为Android设备本地时间&#xff0c;您可以使用java.time包中的类&#xff08;在API 26及以上版本中可用&#xff09;。如果您的应用需要支持较低版本的Android&…

普通男孩的新年创作纪念日

前言 首先在新春佳节&#xff0c;小编在这里祝各位大佬。萌新友友们新年好&#xff0c;希望每一个烟火般的你在新的一年里 offer 多多&#xff0c;薪资多多 &#xff0c;龙行龘龘 &#x1f409; &#x1f409; &#x1f409; &#x1f409;&#xff0c;前程朤朤 ❤️ ❤️ ❤…

【C++】内存详解(堆,栈,静态区)

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

Python电影下载利器:全网资源一键触达

本文分享给大家的是一款全网电影下载利器&#xff0c;采用requests库开发&#xff0c;支持下载各大网站的m3u8格式视频。 与一般下载工具不同&#xff0c;该工具具备强大的功能&#xff0c;能够完整地下载整个电影&#xff0c;并保存为mp4格式文件。 传统下载工具如IDM通常只…

【python】网络爬虫与信息提取--Beautiful Soup库

Beautiful Soup网站&#xff1a;https://www.crummy.com/software/BeautifulSoup/ 作用&#xff1a;它能够对HTML.xml格式进行解析&#xff0c;并且提取其中的相关信息。它可以对我们提供的任何格式进行相关的爬取&#xff0c;并且可以进行树形解析。 使用原理&#xff1a;它能…

Linux第47步_安装支持linux的第三方库和mkimage工具

安装支持linux的第三方库和mkimage工具&#xff0c;做好移植前的准备工作。 编译linux内核之前&#xff0c;需要先在 ubuntu上安装“lzop库”和“libssl-dev库”&#xff0c;否则内核编译会失败。 mkimage工具会在zImage镜像文件的前面添加0x40个字节的头部信息,就可以得到uI…

【Pyhton4Delpi】学习笔记(二)安装验证篇

D12环境下安装P4D。 一、下载 Python4Delphi&#xff08;下称P4D&#xff09;: 下载地址&#xff1a;https://github.com/pyscripter/python4delphi 下载或者克隆P4D到指定的目录&#xff0c;例如&#xff1a;MDS_New&#xff0c;目录结构如下&#xff0c;P4D就是克隆下来的…