鸿蒙小案例-你画我猜

鸿蒙小案例-你画我猜

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,一经查实,立即删除!

相关文章

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

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

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

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

分布式事务详解

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

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

在 JavaScript 中,数据类型是一种用来表示数据的分类,它决定了我们可以对这个数据类型执行哪些操作。在 JavaScript 中有以下几种不同的数据类型: 基本数据类型 字符串 (String):表示一组字符,可以使用引号&#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 漏洞复现

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

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

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

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

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

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

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

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

💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃个人主页 :阿然成长日记 …

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

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

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

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

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

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

软件开发的201个原则

ISBN: 978-7-121-41997-3 作者:【美】Alan M. Davis 译者:叶王、马学翔、吴斌、王冰清 审定:章淼 页数:344页 阅读时间:2023-09-24 推荐指数:★★★★★ 这本书可以说是集开发之大成者了, 如果你…

OWASP TOP10

OWASP TOP10 OWASP网址:http://ww.owasp.org.cn A01:失效的访问控制 例如:越权漏洞 案例1: 正常:每个人登录教务系统,只能查询自己的成绩信息 漏洞:张三登录后可以查看自己的成绩 例如&…

智胜未来,新时代IT技术人风口攻略-第一版(弃稿)

文章目录 抛砖引玉 鸿蒙生态小科普焦虑之下 理想要落到实处校园鼎力 鸿蒙发展不可挡培训入场 机构急于吃红利企业布局 鸿蒙应用规划动智胜未来 技术人风口来临 鸿蒙已经成为行业的焦点,未来的发展潜力无限。作为一名程序员兼UP主,我非常荣幸地接受了邀请…

基于JAVA的贫困地区人口信息管理系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 人口信息管理模块2.2 精准扶贫管理模块2.3 特殊群体管理模块2.4 案件信息管理模块2.5 物资补助模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 人口表3.2.2 扶贫表3.2.3 特殊群体表3.2.4 案件表3.2.5 物资补助表 四…

【Java程序设计】【C00251】基于Springboot的医院信息管理系统(有论文)

基于Springboot的医院信息管理系统(有论文) 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的医院信管系统 本系统分为管理员功能模块、系统功能模块以及医生功能模块。 系统功能模块:医院信管系统,…

161基于matlab的快速谱峭度方法

基于matlab的快速谱峭度方法,选择信号峭度最大的频段进行滤波,对滤波好信号进行包络谱分析。输出快速谱峭度及包络谱结果。程序已调通,可直接运行。 161 信号处理 快速谱峭度 包络谱分析 (xiaohongshu.com)

C++初阶之类与对象(中)——六个默认函数详细解析

个人主页:点我进入主页 专栏分类:C语言初阶 C语言进阶 数据结构初阶 Linux C初阶 欢迎大家点赞,评论,收藏。 一起努力,一起奔赴大厂 目录 一.前言 二.构造函数 2.1构造函数的语法和特性 2.1.1语法 2.…