积分298 / 贡献0

提问9答案被采纳15文章3

[经验分享] 应用开发-手写板(二) 原创

海浪漂啊漂 显示全部楼层 发表于 2024-1-15 20:28:30
在前一篇手写板的文章中(应用开发-手写板),我们通过使用Path实现了一个基本的手写板,但遗憾的是,无法保存所绘制的图像。在本文中,我们将采用canvas和Path2D来重新构建手写板应用。依然只需几十行代码,就能轻松实现手写功能,并添加清空画布以及保存图片的功能。
一、先上效果图:

devecostudio64_Fib0j6tR8T.gif

二、上代码

  1. import picker from '@ohos.file.picker';
  2. import fs from '@ohos.file.fs';
  3. import buffer from '@ohos.buffer';

  4. @Entry
  5. @Component
  6. struct CanvasPage {
  7.   //手写路径
  8.   @State pathCommands: string = '';
  9.   canvas: CanvasRenderingContext2D = new CanvasRenderingContext2D();
  10.   path2D: Path2D = new Path2D();

  11.   build() {
  12.     Column() {
  13.       Row() {
  14.         //清空画布按钮
  15.         Button("清空")
  16.           .margin(10)
  17.           .onClick(() => {
  18.             //将路径置空
  19.             this.path2D = new Path2D();
  20.             //清空画布
  21.             this.canvas.clearRect(0, 0, this.canvas.width, this.canvas.height);
  22.           })
  23.         Button("保存")
  24.           .onClick(() => {
  25.             this.saveImage();
  26.           })
  27.       }

  28.       Canvas(this.canvas)
  29.         .width('100%')
  30.         .height('100%')
  31.         .onTouch((e) => {
  32.           this.onTouchEvent(e);
  33.         })
  34.     }
  35.   }

  36.   onTouchEvent(event: TouchEvent) {
  37.     //手指按下和移动时的位置转换成像素位置
  38.     let x = (event.touches[0].x);
  39.     let y = (event.touches[0].y);
  40.     switch (event.type) {

  41.     //手指按下
  42.       case TouchType.Down:
  43.       //移动到(x,y)点
  44.         this.path2D.moveTo(x, y);
  45.         break;

  46.     //画线到(x,y)点
  47.       case TouchType.Move:
  48.         this.path2D.lineTo(x, y);
  49.       //画笔颜色
  50.         this.canvas.strokeStyle = "#0000ff";
  51.       //画笔粗细
  52.         this.canvas.lineWidth = 5;
  53.       //画出线段
  54.         this.canvas.stroke(this.path2D);
  55.         break;
  56.       default:
  57.         break;
  58.     }
  59.   }

  60.   saveImage() {
  61.     //获取图片的base64字符串
  62.     let imageStr = this.canvas.toDataURL().split(',')[1];
  63.     //文件保存路径
  64.     let uri = '';
  65.     try {
  66.       let PhotoSaveOptions = new picker.PhotoSaveOptions();
  67.       //保存图片默认名称
  68.       PhotoSaveOptions.newFileNames = ['11111.png'];
  69.       let photoPicker = new picker.PhotoViewPicker();
  70.       //调起系统的图片保存功能
  71.       photoPicker.save(PhotoSaveOptions).then((PhotoSaveResult) => {
  72.         uri = PhotoSaveResult[0];
  73.         //打开文件
  74.         let file = fs.openSync(uri, fs.OpenMode.READ_WRITE);
  75.         //base64字符串转成buffer
  76.         const decodeBuffer = buffer.from(imageStr, 'base64').buffer;
  77.         //写入文件
  78.         fs.writeSync(file.fd, decodeBuffer);
  79.         //关闭文件
  80.         fs.closeSync(file);
  81.       }).catch((err: Error) => {
  82.         console.error(err + '');
  83.       })
  84.     } catch (e) {
  85.       console.error(e);
  86.     }
  87.   }
  88. }
复制代码

在这段代码中,根据功能划分,主要涵盖了三个关键操作:绘制路径、清空画布和保存画布。

一、绘制路径

        在绘制路径方面,代码通过Canvas执行图像绘制,同时借助Path2D定义了具体的绘制路径。手写路径的生成通过记录手指按下和移动的位置实现。具体操作包括:

  1. this.path2D.moveTo(x, y)  // 移动到(x, y)点
  2. this.path2D.lineTo(x, y)  // 画线到(x, y)点
复制代码
二、清空画布

清空画布的操作分为两步:

1.将路径置空

  1. // 重新生成新的Path2D对象,因为HarmonyOS中的Path2D没有reset方法
  2. this.path2D = new Path2D();  
复制代码

2.清空canvas

  1. this.canvas.clearRect(0, 0, this.canvas.width, this.canvas.height);
复制代码

三、保存画布

        保存画布的过程主要由saveImage方法完成,依赖于@ohos.file.picker组件,调用系统的图片保存功能。具体步骤包括:

1.通过PhotoViewPicker的save方法获取用户选择的保存文件路径。

2.利用Canvas的toDataURL()方法将Canvas转换为base64字符串形式的图片。

3.通过@ohos.buffer将base64字符串转换为buffer。

4.最终,通过@ohos.file.fs将buffer写入文件,文件的路径为之前获取的保存路径。

        这一系列步骤成功实现了将绘制的图像保存为一个完整的图片文件。整体而言,代码清晰地展示了绘制路径、清空画布和保存画布的功能实现。

©著作权归作者所有,转载或内容合作请联系作者

您尚未登录,无法参与评论,登录后可以:
参与开源共建问题交流
认同或收藏高质量问答
获取积分成为开源共建先驱

精彩评论1

kazike

沙发 发表于 2024-9-29 10:50:31
牛逼牛逼,请问有办法实现那种 笔锋效果不,就是画图过程可以随着按压改变画笔粗细,我用了您这个案例,发现改变画笔粗细的时候,会把之前绘制的图的粗细也改变  还望大佬能看看

Copyright   ©2023  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

返回顶部