HarmonyOS 对XComponent截图失败?

如下demo,对XComponent截图失败

snapshot = (): image.PixelMap | null => {
  if (this.surfaceId?.length !== 0) {
    const region: image.Region = {
      x: 0,
      y: 0,
      size: {
        width: this.windowRect[0],
        height: this.windowRect[1]
      }
    };
    // 在EntryAbility设置了沉浸式页面,所以size是屏幕宽高,不然接口crash
    return image.createPixelMapFromSurfaceSync(this.surfaceId, region);
  }
  return null;
}
阅读 661
1 个回答

问题根因:image.createPixelMapFromSurfaceSync(this.surfaceId, region)截图的region需要在组件区域内,报错原因的region的size设置过大。

可参考如下demo:

import XComponentContext from "../interface/XComponentContext"
import { image } from '@kit.ImageKit';
import componentUtils from '@ohos.arkui.componentUtils';

@Entry
@Component
struct Index {
  @State currentStatus: string = "init";
  private xComponentContext: XComponentContext | undefined = undefined;
  @State pixelMap: image.PixelMap | null = null;
  xcomponentController: XComponentController = new XComponentController()
  // 纹理信息id
  private surfaceId: string = '';
  // 点击穿透阈值
  private clickThroughAlpha = 0.78;

  snapshot = (size: Size): image.PixelMap | null => {
    if (this.surfaceId?.length !== 0) {
      const region: image.Region = {
        x: 0,
        y: 0,
        size: size
      };
      return image.createPixelMapFromSurfaceSync(this.surfaceId, region);
    }
    return null;
  }
  // 读取点击区域信息
  readPixel = (pixelMap: image.PixelMap, x: number, y: number): image.PositionArea => {
    const area: image.PositionArea = {
      pixels: new ArrayBuffer(8),
      offset: 0,
      stride: 4,
      region: { size: { height: 1, width: 1 }, x: vp2px(x), y: vp2px(y) }
    };
    pixelMap.readPixelsSync(area)
    return area;
  }

  build() {
    Column() {
      Row() {
        Text('Native XComponent Sample')
          .fontSize('24fp')
          .fontWeight(500)
          .margin({
            left: 24,
            top: 12
          })
      }
      .margin({ top: 24 })
      .width('100%')
      .height(56)

      Column({ space: 10 }) {
        XComponent({
          id: 'xcomponentId',
          type: XComponentType.SURFACE,
          libraryname: 'nativerender',
          controller: this.xcomponentController,
        })
          .onLoad((xComponentContext) => {
            this.surfaceId = this.xcomponentController.getXComponentSurfaceId()
            this.xComponentContext = xComponentContext as XComponentContext;
            this.currentStatus = "index";
          })
          .onDestroy(() => {
            console.log('onDestroy');
          })
          .id("xcomponent")
      }
      .height('40%')
      .width('100%')
      .margin({
        top: 27,
        left: 12,
        right: 12
      })
      // 自定义事件拦截:触摸点透明度小于阈值,需要透传给兄弟节点;触摸点透明度大于等于阈值,仅自己和子节点响应事件和手势
      .onTouchIntercept((touchEvent: TouchEvent) => {
        if (!this.surfaceId) {
          this.surfaceId = this.xcomponentController.getXComponentSurfaceId()
        }
        const componentInfo:componentUtils.ComponentInfo = componentUtils.getRectangleById("xcomponent");

        if (!this.surfaceId || componentInfo.size.width === 0 || componentInfo.size.height === 0) {
          return HitTestMode.Transparent;
        }

        // 截图
        this.pixelMap = this.snapshot(componentInfo.size);

        if (this.pixelMap) {
          const x = touchEvent.touches[0].x;
          const y = touchEvent.touches[0].y;

          const area = this.readPixel(this.pixelMap, x, y);

          if (area?.pixels) {
            const byteArray = new Uint8Array(area!.pixels);
            const alpha = byteArray[3] / 255.0;
            console.log(`testTag: 触摸点位置:x: ${x} y: ${y} 透明度alpha: ${alpha}`);
            return alpha <= (1 - this.clickThroughAlpha) ? HitTestMode.Transparent : HitTestMode.Default;
          }
        }
        return HitTestMode.Transparent;
      })

      Image(this.pixelMap)
        .objectFit(ImageFit.Contain)
        .height(200)
        .width(200)
    }
    .width('100%')
    .height('100%')
  }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进