手把手教你使用HarmonyOS鸿蒙Next中ArkTS的canvas实现签名板功能

手把手教你使用HarmonyOS鸿蒙Next中ArkTS的canvas实现签名板功能 作者:陈杨

作为一名web前端开发者,还在持续自学HarmonyOS,学习过程中我会分享自己做的一些工具,包括开发难点与解决方案,希望对各位HarmonyOS开发者有所启发。

这次我要分享的是使用ArkTS中的canvas实现签名板的功能,canvas画布大家都很熟悉,我们会用它经常实现一些画板或者图表、表格之类的功能。canvas签名板是我在开发APP过程中实现的一个功能,开发过程中也是遇到比较多的问题。我会按照以下几点来讲解开发整个过程:

一、屏幕旋转

实现签名板的第一个功能就是旋转屏幕。旋转屏幕在各种框架中都有不一样的方式,比如:

  • 在H5端,我们一般是使用CSS中的transform属性中的rotate()方法来强制将网页横屏,然后实现一系列功能
  • 在嵌套第三方APP中,我们一般是调用对应的SDK提供的方法,即可实现旋转屏幕
  • 实现方式还有很多,各有千秋,相信HarmonyOS也会提供对应API方法来设置旋转屏幕。

而我自己则是在页面内通过 Window 对象的 setPreferredOrientation() 方法实现横竖屏切换。以下是我实现的完整代码:

// 在EntryAbility.ts中获取窗口实例并赋值给全局变量,如此所有页面都可以通过全局变量去修改窗口信息,不需要重新获取
import { UIAbility } from '@ohos.app.ability.UIAbility';
import { window } from '@ohos.window';

export default class EntryAbility extends UIAbility {
  onWindowStageCreate(windowStage: window.WindowStage) {
    windowStage.getMainWindow((err, data) => {
      if (err.code) {
        console.error('获取失败' + JSON.stringify(err));
        return;
      }
      console.info('获取主窗口的实例:' + JSON.stringify(data));
      globalThis.windowClass = data // 赋值给全局变量windowClass
    });
  }
}

// 在具体页面中的使用
import { window } from '@ohos.window';

@Entry
@Componentstruct SignatureBoard {

  onPageShow() {
    // 获取旋转的方向,具体可以查看对应文档
    let orientation = window.Orientation.LANDSCAPE_INVERTED;
    try {
      // 设置屏幕旋转
      globalThis.windowClass.setPreferredOrientation(orientation, () => {});
    } catch (exception) {
      console.error('设置失败: ' + JSON.stringify(exception));
    }
  }
}

二、canvas画布

解决了屏幕旋转问题,接下来实现签名功能。因为在之前就已经开发过,只要将对应的语法转成ArkTS的语法就好。以下是代码解析:

2.1 按照官方文档使用canvas组件

@Entry
@Component
struct SignatureBoard {
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Column() {
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#fff')
        .onReady(() => {
        })
    }
    .width('100%')
    .height('100%')
  }
}

2.2 设置画笔的属性以及绑定手势功能。

在js中我们基本都是使用鼠标事件来实现的,而在ArkTS中是通过手势方法来监听手指在屏幕上的操作,有很多种,大家需要用到的可以去查看对应的文档。

build() {
  Column() {
    Canvas(this.context)
      .width('100%')
      .height('100%')
      .backgroundColor('#fff')
      .onReady(() => {
        this.context.lineWidth = 3; // 设置画笔的粗细
        this.context.strokeStyle = "#000"; // 设置画笔的颜色
        // 还可以设置很多,根据自己业务需要
      })
      .gesture(
        PanGesture(this.panOption)
          .onActionStart((event: any) => {
            // 手指按下的时候
          })
          .onActionUpdate((event: any) => {
            // 手指移动的时候
          })
          .onActionEnd(() => {
            // 手指离开的时候
          })
      )
  }
}

2.3 我们实现的手势的绑定,那么就可以实现手指在屏幕上滑动之后画布就绘画出对应的轨迹路线了,这里将会使用到一些画布的功能。

@Entry
@Componentstruct SignatureBoard {
  private lastX: number = 0;
  private lastY: number = 0;
  private isDown: Boolean = false;
  private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.All, distance: 1 })
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  draw(startX, startY, endX, endY) {
    // 起点
    this.context.moveTo(startX, startY);
    // 终点
    this.context.lineTo(endX, endY);
    // 调用 stroke,即可看到绘制的线条
    this.context.stroke();
  }

  build() {
    Column() {
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#fff')
        .onReady(() => {
          this.context.lineWidth = 3;
          this.context.strokeStyle = "#000";
        })
        .gesture(
          PanGesture(this.panOption)
            .onActionStart((event: any) => {
              this.isDown = true;
              // 按下时的点作为起点
              this.lastX = event.localX;
              this.lastY = event.localY;
              // 创建一个新的路径
              this.context.beginPath();
            })
            .onActionUpdate((event: any) => {
              // 没有按下就不管
              if (!this.isDown) return;
              const offsetX = event.localX
              const offsetY = event.localY
              // 调用绘制方法
              this.draw(this.lastX, this.lastY, offsetX, offsetY);
              // 把当前移动时的坐标作为下一次的绘制路径的起点
              this.lastX = offsetX;
              this.lastY = offsetY;
            })
            .onActionEnd(() => {
              this.isDown = false;
              // 关闭路径
              this.context.closePath();
            })
        )
    }
    .width('100%')
    .height('100%')
  }
}

以上就是我们实现签名板的完整思路以及代码了,有几个需要注意的点是:

  1. new PanGestureOptions 实例的时候需要把 distance 设置小一点,值越小灵敏度就越高。
  2. PanGesture 的回调方法中 event 参数,官方默认给的属性类型为 GestureEvent。但是我在编辑器源码中查看该属性没有我们定义我们想要的 localXlocalY,但是实际是有返回的,如果直接用编辑器会报错。所以需要将 event 定为 any 类型,这样就可以获取且不报错了。

这次的画布签名板的功能就分享这些,希望能够帮助各位开发者,后续会继续分享出更多在项目中经常用到的工具。


更多关于手把手教你使用HarmonyOS鸿蒙Next中ArkTS的canvas实现签名板功能的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

event.fingerList[0].localX;

localX是这样取的 不用转any

更多关于手把手教你使用HarmonyOS鸿蒙Next中ArkTS的canvas实现签名板功能的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


将 event 改为 any 类型太牛了,我就一直获取起点 x 坐标取不到,通过你这个方式取到了。

没有图片啊,看不到效果

在HarmonyOS鸿蒙Next中,使用ArkTS的Canvas组件实现签名板功能的步骤如下:

  1. 创建Canvas组件:在布局文件中添加Canvas组件,设置其宽高以覆盖签名区域。
  2. 初始化画笔:在代码中获取Canvas上下文,设置画笔颜色、粗细等属性。
  3. 监听触摸事件:通过onTouchEvent监听用户触摸屏幕的动作,记录触摸点的坐标。
  4. 绘制路径:在move事件中,使用lineTo方法连接触摸点,形成连续的笔迹,并通过stroke方法绘制到Canvas上。
  5. 清除画布:提供一个按钮或手势,调用clearRect方法清除Canvas内容,实现签名重置功能。

通过这些步骤,你可以轻松实现一个简单的签名板功能,适用于电子签收、手写笔记等场景。

回到顶部