目录

Web组件长截图

场景描述

Web组件的长截图功能可以对网页内容进行截图,旨在为用户提供快速便捷的数据信息分享和保存方式,确保用户能够完整地捕获和分享浏览的网页信息。

实现效果

点击“一键截图”按钮即可完成整个网页的长截图,并可将截图保存至相册。

功能实现

Web组件可以通过滚动截图方案以及使用WebView提供的webPageSnapshot进行长截图。其中WebView提供的webPageSnapshot方法比较适合结构简单、静态元素的页面长截图,如果网页中有动态资源,结构相对复杂,比如有固定的标题头等,推荐使用滚动截图方案。

使用滚动截图的方式进行网页长截图

Web组件滚动长截图和滚动组件长截图开发流程大体一样,主要是控制组件的滚动的方法不同。List组件使用的是Scroller,而Web组件使用的是webViewController。

在滚动截图过程中,webViewController负责控制Web组件的滚动,通过调用webViewController.scrollBy方法来实现。为了判断是否已滚动到底部,使用this.webViewController.getPageHeight() 方法获取网页内容的总高度,详情可参考获取网页内容高度,并将当前偏移量this.curYOffset加上组件自身的高度与网页总高度进行比较。如果两者的和小于网页总高度,则表示尚未触底。

async snapAndMerge() {
  try {
    this.scrollYOffsets.push(this.curYOffset);
    const pixelMap = await this.getUIContext().getComponentSnapshot().get(WEB_ID);
    let area: image.PositionArea =
      await ImageUtils.getSnapshotArea(this.getUIContext(), pixelMap, this.scrollYOffsets, this.webComponentWidth,
        this.webComponentHeight);
    this.areaArray.push(area);
    if (Math.ceil(this.curYOffset + this.webComponentHeight) < this.webviewController.getPageHeight()) {
      this.webviewController.scrollBy(0, this.scrollHeight, 500);
      await CommonUtils.sleep(600)
      await this.snapAndMerge();
    } else {
      this.mergedImage =
        await ImageUtils.mergeImage(this.getUIContext(), this.areaArray,
          this.scrollYOffsets[this.scrollYOffsets.length - 1], this.webComponentHeight);
    }
  } catch (err) {
    let error = err as BusinessError;
    Logger.error(TAG, `snapAndMerge err, errCode: ${error.code}, error message: ${error.message}`);
  }
}

使用webPageSnapshot()方法进行网页长截图

Web组件使用webPageSnapshot()方法实现长截图的步骤如下:

  1. Web初始化,调用enableWholeWebPageDrawing()方法开启网页全量绘制能力。

    aboutToAppear(): void {
      try {
        webview.WebviewController.initializeWebEngine();
        webview.WebviewController.enableWholeWebPageDrawing();
        webview.WebviewController.prepareForPageLoad(EXAMPLE_URL, true, 2);
      } catch (err) {
        let error = err as BusinessError;
        Logger.error(TAG, `web snapshot init err, errCode: ${error.code}, error message: ${error.message}`);
      }
    }
  2. 获取网页内容高度和宽度。

    async getWebSize() {
      const SCRIPT = '[document.documentElement.scrollWidth, document.documentElement.scrollHeight]';
      try {
        this.webviewController.runJavaScriptExt(SCRIPT).then((result) => {
          if (result.getType() === webview.JsMessageType.ARRAY) {
            this.h5Width = (result.getArray() as number[])[0];
            this.h5Height = (result.getArray() as number[])[1];
            Logger.info(TAG, `h5Width is ${this.h5Width}, h5Height is ${this.h5Height}`);
          }
        }).catch((error: BusinessError) => {
          Logger.error(TAG, `getWebSize exception, errCode: ${error.code}, error message: ${error.message}`);
        });
      } catch (error) {
        let err = error as BusinessError;
        Logger.error(TAG, `getWebSize failed, errCode: ${err.code}, error message: ${err.message}`);
      }
    }
  3. 调用webPageSnapshot()方法,进行网页截图。

    async webSnapshot() {
      try {
        this.webviewController.webPageSnapshot({ id: WEB_ID, size: { width: this.h5Width, height: this.h5Height } },
          async (error, result) => {
            if (result) {
              this.longPixelMap = result.imagePixelMap;
            }
          });
      } catch (error) {
        let err = error as BusinessError;
        Logger.error(TAG, `webSnapshot err, errCode: ${err.code}, error message: ${err.message}`);
      }
    }

加载网络html文件时,需要在entry/src/main路径下的module.json5中配置网络权限。示例代码如下所示:

{
 "module": {
   "requestPermissions": [
     {
       "name": "ohos.permission.INTERNET"
     }
   ]
 }
}