HarmonyOS 鸿蒙Next 折叠屏调用pixelMap的crop方法时会报错

HarmonyOS 鸿蒙Next 折叠屏调用pixelMap的crop方法时会报错 我们现在需要进行web组件内容的长截图,最后一页和倒数第二页的截图必然会有重复部分,需要进行切割,但现在直板机全部正常,但折叠屏调用crop方法时必定报错。经过排查,pixelMap的获取没有问题,传的参数也没有问题,所以现在找不到报错原因,只有一个报错代码62980109,也查不出问题在哪,希望有大佬回复一下

4 回复

错误62980109表示对图片的裁剪出现错误,如裁剪区域不合理,检查下crop的size的width和height对不对。更多的错误处理可参考图片错误码

如果还有问题,需要发下你使用crop方法的代码。

更多关于HarmonyOS 鸿蒙Next 折叠屏调用pixelMap的crop方法时会报错的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


截图函数

async snapShot(): Promise<image.PixelMap> {
  return new Promise(async (resolve, reject) => {
    // 获取Web页面尺寸
    this.getWebSize();
    // 截图前的状态初始化
    await this.beforeSnapshot();
    // 使用Canvas离屏绘制在缓冲区拼接截图
    const canvasSetting: RenderingContextSettings = new RenderingContextSettings(true);
    const offCanvasCtx: OffscreenCanvasRenderingContext2D =
      new OffscreenCanvasRenderingContext2D(this.h5Width, this.h5Height, canvasSetting);
    // 前置常量
    const snipTimes = Math.ceil(this.h5Height / this.webHeight);
    const lastTime = snipTimes - 1;
    const leftoverHeight = this.h5Height % this.webHeight;
    let cropLeftover: image.Region = { x: 0, y: 0, size: { height: 0, width: 0 } }
    if (this.WebTouchBottom) {
      // 这里要分两种情况,1.滚动到底部时,裁剪应该取最后一张除去重复部分以外的底部
      cropLeftover = {
        x: 0,
        y: vp2px(this.webHeight - leftoverHeight),
        size: {
          height: vp2px(leftoverHeight),
          width: vp2px(this.webWidth)
        }
      };
    } else {
      // 2.未滚动到底部时,裁剪应该取最后一张leftoverHeight的上部分
      cropLeftover = {
        x: 0,
        y: 0,
        size: {
          height: vp2px(leftoverHeight),
          width: vp2px(this.webWidth)
        }
      };
    }

    if (snipTimes === 1) {
      const curSnip = await componentSnapshot.get('receiptShare');
      offCanvasCtx.drawImage(curSnip, 0, 0, this.webWidth, this.webHeight);
    } else {
      // 开始截图
      for (let i = 0; i < snipTimes; i++) {
        const curSnip = await componentSnapshot.get('receiptShare');
        // 最后一次截图需要特殊处理,去除重复部分
        if (i === lastTime) {
          cropLeftover = {
            x: 0,
            y: vp2px(this.webHeight - leftoverHeight),
            size: {
              height: vp2px(leftoverHeight),
              width: vp2px(this.webWidth)
            }
          };
          try {
            await curSnip.crop(cropLeftover);
          } catch (e) {
            YTLog.error(JSON.stringify(e))
          }
          offCanvasCtx.drawImage(curSnip, 0, this.webHeight * i - 2, this.webWidth, leftoverHeight);
        } else {
          offCanvasCtx.drawImage(curSnip, 0, this.webHeight * i, this.webWidth, this.webHeight);
        }
        // 继续滚动
        this.mWebviewController.scrollBy(0, this.webHeight);
        // 延时保证滚动完成
        await this.sleep(200);
      }
    }

    // 截图后的操作
    await this.afterSnapshot();
    // 获取pixelMap
    this.mergedImage = offCanvasCtx.getPixelMap(0, 0, this.h5Width, this.h5Height);
    resolve(this.mergedImage)
  })
}

截图前获取尺寸

getWebSize() {
  const SCRIPT = '[document.documentElement.scrollWidth, document.documentElement.scrollHeight]';
  this.mWebviewController.runJavaScriptExt(SCRIPT).then((result) => {
    try {
      switch (result.getType()) {
        case webview.JsMessageType.ARRAY:
          this.h5Width = (result.getArray() as number[])[0]; // 单位是vp
          this.h5Height = (result.getArray() as number[])[1];
          break;
        default:
          break;
      }
    } catch (e) {

    }
  });
}

截图开始前的操作

  • 保存网页当前位置,用于恢复状态
  • 截图当前页面作为遮罩层,避免用户察觉组件的滚动,提高用户体验
  • Web页面滚动到顶部,准备开始截图
  • 设置截图后小弹窗的位置,提示用户暂时不要操作,等待截图
  • 开启提示小弹窗
async beforeSnapshot() {
  // 保存网页当前位置,用于恢复
  this.xOffsetBefore = this.curXOffset;
  this.yOffsetBefore = this.curYOffset;
  this.h5Height = this.curYOffset + Math.ceil(this.webHeight);
  // TODO: 知识点: 使用componentSnapshot.get接口直接获取组件的渲染结果,而不需要将屏幕截图
  this.webMaskImage = await componentSnapshot.get('receiptShare');
  this.mWebviewController.scrollTo(0, 0);
  // 延时确保已经滚动到了顶部
  await this.sleep(200);
}

截图之后的操作

  • 恢复web页面到截图之前的位置
  • 取消遮罩层
async afterSnapshot() {
  this.mWebviewController.scrollTo(this.xOffsetBefore, this.yOffsetBefore);
  await this.sleep(200);
}
sleep(ms: number): Promise<void> {
  return new Promise(resolve => setTimeout(resolve, ms));
}

webHeight是webView的高度,leftoverHeight是重叠部分的高度,h5Height是前端页面的高度,

在HarmonyOS鸿蒙Next系统中,当调用pixelMapcrop方法时出现报错,这通常与pixelMap对象的状态、传递的参数或方法调用的上下文有关。以下是一些可能的原因及解决方法(不涉及Java或C语言):

  1. 检查pixelMap对象:确保pixelMap对象已正确初始化且不为空。如果pixelMap是空的或未正确加载,调用crop方法将会失败。

  2. 验证裁剪参数:crop方法通常接受一个Rect对象作为参数,用于指定裁剪区域。确保这个Rect对象的坐标和尺寸在pixelMap的有效范围内。如果Rect的坐标或尺寸超出pixelMap的边界,将会导致错误。

  3. 权限问题:确保应用具有访问和操作图像数据的必要权限。在鸿蒙系统中,可能需要特定的权限来读取或修改图像数据。

  4. API兼容性:检查你所使用的鸿蒙系统版本是否支持你正在调用的crop方法的特定版本。有时,API的更新或更改可能导致旧代码在新版本上运行失败。

如果以上步骤均无法解决问题,可能是系统内部bug或特定场景下的异常。此时,建议直接联系鸿蒙系统的官方客服进行进一步的排查和解决。

如果问题依旧没法解决请联系官网客服, 官网地址是 https://www.itying.com/category-93-b0.html

回到顶部