鸿蒙小案例-你画我猜

鸿蒙小案例-你画我猜

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.hqwc.cn/news/467395.html

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

相关文章

2.12.。

1、选择芯片型号——STM32F051K8 2、开启调试功能 3、配置时钟 4、配置时钟树 5、工程管理

LeetCode:70.爬楼梯

前言:好家伙,一直以为动态规划是啥高大上的,解释那么多,在我看来不过是找规律罢了, 写那么多"专业术语"咋看咋像糊弄人的 (手动扶额) 另外,通项公式虽然抽象还能接受,但是矩阵快速幂…

接口测试06 -- pytest接口自动化封装Loggin实战

1. 接口关键字封装 1.1 基本概念 接口关键字封装是指:将接口测试过程中常用的操作、验证封装成可复用的关键字(或称为函数、方法),以提高测试代码的可维护性和可复用性。 1.2 常见的接口关键字封装方式 1. 发送请求:封装一个函数,接受参数如请求方法、URL、请求头、请求…

游泳耳机排行榜前十名,精选四款热门游泳耳机排行榜品牌推荐

游泳,一项被誉为“最全面的运动”的健身方式。无论是对于年轻人还是中老年人,无论体重大小,游泳都能带来无与伦比的益处。在水中的阻力是地面上的十二倍,这使得游泳成为了一种全身性的锻炼方式,能够让身体的每一块肌肉…

宽带高效非对称连续J/F-1模式Doherty 功率放大器设计(2023.11 MTT)-从理论到ADS版图

宽带高效非对称连续J/F-1模式Doherty 功率放大器设计(2023.11 MTT)-从理论到ADS版图 这个文章实现的效果非常好,非常值得大家去阅读复现(见前言介绍),但是我复现出现了一点困难,效果调不到那么好(带宽只是…

【教程】最新使用Shamrock搭建QQ机器人

转载请注明出处:小锋学长生活大爆炸[xfxuezhang.cn] 背景介绍 官方原版Shamrock的作者已经删库跑路了,所以我们使用这个:OpenShamrock 文档在这里,但访问可能需要点魔法:快速开始指南 步骤也简单,这里以无R…

【在Linux世界中追寻伟大的One Piece】Linux是从哪里来的?又是怎么发展的?基本指令你知道哪些?

目录 1 -> Linux背景 1.1 -> Linux发展史 1.1.1 -> UNIX发展历史 1.1.2 -> Linux发展历史 1.2 -> 开源 1.3 -> 官网 1.4 -> 企业应用现状 1.5 -> 发行版本 1.6 -> OS概念,定位 2 -> Linux下基本指令 2.1 -> Is指令 2…

假期作业 10

1.整理磁盘操作的完整流程,如何接入虚拟机,是否成功识别,对磁盘分区工具的使用,格式化,挂载以及取消挂载 U盘接入虚拟机 在虚拟机--->可移动设备--->找到U盘---->连接 检测U盘是否被虚拟机识别 ls /dev/s…

Solidworks:从草图到工程图纸,掌握正确的工作流程

1. 草图不及太在意构造线和尺寸标注的美观性,只要确保模型尺寸正确即可 因为草图不是最终输出的,这个阶段的工作重点是建立尺寸正确的实体模型,所以不要在意构造线和尺寸标注是否美观。 2. 工程图纸中标注尽量按照操作提示放置位置 工程图…

【Chrono Engine学习总结】5-sensor-5.1-sensor基础并创建一个lidar

由于Chrono的官方教程在一些细节方面解释的并不清楚,自己做了一些尝试,做学习总结。 1、Sensor模块 Sensor模块是附加模块,需要单独安装。参考:【Chrono Engine学习总结】1-安装配置与程序运行 Sensor Module Tutorial Sensor …

springboot182基于springboot的网上服装商城

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计,课程设计参考与学习用途。仅供学习参考, 不得用于商业或者非法用途,否则,一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

深入理解梯度加权类激活热图(Grad-CAM)

深入理解梯度加权类激活热图(Grad-CAM) 项目背景与意义 在深度学习领域,模型的预测能力往往是黑盒子,难以解释。梯度加权类激活热图(Grad-CAM)作为一种可解释性技术,能够帮助模型开发者更好地…