目录

StylusFrameBoost (Stylus Frame Boost)

This module provides the stylus frame boost capability. By calling the stylus frame boost API, you can reduce the stylus writing latency of handwriting apps at a high frame rate.

Since: 26.0.0

Modules to Import

import { StylusFrameBoost } from '@kit.Penkit';

forceRefreshOneFrame

forceRefreshOneFrame(action: number): number

Reduces the stylus writing latency of handwriting apps at a high frame rate.

Model restriction: This API can be used only in the stage model.

System capability: SystemCapability.Stylus.Handwrite

Since: 26.0.0

Parameters:

Parameter Type Mandatory Description
action number Yes

Stylus touch event.

0: down

1: up

2: move

3: cancel

Returns:

Type Description
number

Query result.

0: The stylus frame boost is successfully executed.

1: The stylus frame boost fails to be executed.

Example:

import { LengthMetricsUnit } from '@kit.ArkUI';
import { inputDevice } from '@kit.InputKit';
import { StylusFrameBoost } from '@kit.Penkit';

@Entry
@Component
struct StylusFrameBoostDemo {
  private device: PencilHelper = new PencilHelper()
  private settings: RenderingContextSettings = new RenderingContextSettings(false)
  private ctx: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings, LengthMetricsUnit.PX)
  private stylusFrameBoost: StylusFrameBoost = new StylusFrameBoost();

  build() {
    Column() {
      Canvas(this.ctx)
        .width('100%')
        .height('100%')
        .onReady(() => {
          this.ctx.lineWidth = 20
          this.ctx.beginPath()
          this.ctx.lineCap = 'round'
          this.ctx.strokeStyle = Color.Black;
        })
        .onTouch((event: TouchEvent) => {
          // Check whether a stylus is connected. This API depends on the stylus service.
          if (this.device.hasPencil) {
            if (event.sourceTool === SourceTool.Pen || event.sourceTool === SourceTool.MOUSE ||
              event.sourceTool === SourceTool.Finger) {
              this.handleWriteEvent(event)
            }
          }
        })
    }
  }

  aboutToAppear(): void {
    this.device.init();
  }

  handleWriteEvent(event: TouchEvent) {
    if (event.touches.length <= 0) {
      return
    }
    const touch = event.changedTouches[0]
    let x = touch.x
    let y = touch.y
    switch (event.type) {
      case TouchType.Down:
        this.ctx.moveTo(vp2px(x), vp2px(y));
        try {
          this.stylusFrameBoost.forceRefreshOneFrame(event.type);
        } catch (error) {
          console.error('stylusFrameBoost failed: ', error);
        }
        break
      case TouchType.Move:
        this.ctx.lineTo(vp2px(x), vp2px(y));
        try {
          this.stylusFrameBoost.forceRefreshOneFrame(event.type);
        } catch (error) {
          console.error('stylusFrameBoost failed: ', error);
        }
        break
      case TouchType.Up:
      case TouchType.Cancel:
        this.ctx.lineTo(vp2px(x), vp2px(y))
        try {
          this.stylusFrameBoost.forceRefreshOneFrame(event.type);
        } catch (error) {
          console.error('stylusFrameBoost failed: ', error);
        }
        break
    }
    this.ctx.stroke();
  }
}

class PencilHelper {
  private _hasPencil: boolean = false
  private pencilId: number = 0

  public get hasPencil(): boolean {
    return this._hasPencil
  }

  async init() {
    const deviceIds = await inputDevice.getDeviceList()
    inputDevice.on('change', async (device: inputDevice.DeviceListener) => {
      if (device.type === 'add') {
        const isPencil = await this.isPencil(device.deviceId)
        if (isPencil) {
          this._hasPencil = true
          this.pencilId = device.deviceId
        }
      } else if (this.pencilId === device.deviceId) {
        // Delete the information that cannot be queried. You can determine the information only based on the previous ID.
        this._hasPencil = false
        this.pencilId = 0
      }
    })
    for (const id of deviceIds) {
      const info = await inputDevice.getDeviceInfo(id)
      const isPencil = await this.isPencil(id)
      if (isPencil) {
        this._hasPencil = true
        this.pencilId = id
        break
      }
    }
  }

  async isPencil(deviceId: number) {
    const info = await inputDevice.getDeviceInfo(deviceId)
    return info.name.toLowerCase().indexOf('pencil') >= 0
  }
}