手把手教你使用 ArkTS 中的 canvas 實現簽名板功能

HarmonyOS開發者社群發表於2023-12-20

一、螢幕旋轉

●  實現簽名板的第一個功能就是旋轉螢幕。旋轉螢幕在各種框架中都有不一樣的方式,比如:在 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,  ( err) => {});     }  catch (exception) {        console. error( '設定失敗: ' +  JSON. stringify(exception));     }   } }


二、canvas 畫布

解決了螢幕旋轉問題,接下來實現簽名功能。因為在之前就已經開發過,只要將對應的語法轉成 ArkTS 的語法就好。以下是程式碼解析:2.1 按照官方文件使用 canvas 元件



@Entry@Component
struct 
SignatureBoard {
  
private 
settingsRenderingContextSettings = 
new 
RenderingContextSettings(
true)
  
private 
contextCanvasRenderingContext2D = 
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。但是我在編輯器原始碼中檢視該屬性沒有我們定義我們想要的 localX、localY,但是實際是有返回的,如果直接用編輯器會報錯。所以需要將 event 定為 any 型別,這樣就可以獲取且不報錯了。


這次的畫布簽名板的功能就分享這些,希望能夠幫助各位開發者,後續會繼續分享出更多在專案中經常用到的工具。


來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70009402/viewspace-3000741/,如需轉載,請註明出處,否則將追究法律責任。

相關文章