We use essential cookies for the website to function, as well as analytics cookies for analyzing and creating statistics of the website performance. To agree to the use of analytics cookies, click "Accept All". You can manage your preferences at any time by clicking "Cookie Settings" on the footer. More Information.

Only Essential Cookies
Accept All

StylusFrameBoost (Stylus Frame Boost)

Phone5.0.0(12)+PC/2in15.0.1(13)+Tablet5.0.0(12)+

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

Phone26.0.0+PC/2in126.0.0+Tablet26.0.0+

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:

Expand
Parameter Type Mandatory Description
action number Yes

Stylus touch event.

0: down

1: up

2: move

3: cancel

Returns:

Expand
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
  }
}