如何对指定区域进行截图
===========

#### 问题现象

页面中有一张图片需要进行截图保存，那么，如何实现对页面中的指定区域进行截图？

#### 背景知识

*   [componentSnapshot](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-arkui-componentsnapshot)：提供获取组件截图的能力，包括已加载的组件的截图和没有加载的组件的截图。组件截图只能够截取组件大小的区域，如果组件的绘制超出了它的区域，或子组件的绘制超出了父组件的区域，这些在组件区域外绘制的内容不会在截图中呈现。兄弟节点堆叠在组件区域内，截图不会显示兄弟组件。
*   [screenshot.pick](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-screenshot#screenshotpick)：获取屏幕截图，当前仅支持获取displayId为0的屏幕截图（如果需要对扩展屏截图，可以通过[capture](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-screenshot#screenshotcapture14)接口实现）。

#### 解决方案

实现对指定区域进行截图有以下方法：

*   **方法一**：可以使用系统提供的@ohos.arkui.componentSnapshot (组件截图)能力。但需要注意的是：组件截图只能够截取组件大小的区域，如果组件的绘制超出了它的区域，或子组件的绘制超出了父组件的区域，这些在组件区域外绘制的内容不会在截图中呈现。
*   **方法二**：可以使用screenshot.pick获取屏幕截图，调用该方法时系统会自动提示"请拖动画出矩形"，矩形区域即为截图区域。注：该方法仅支持2in1设备使用。

示例代码如下：

import { image } from '@kit.ImageKit';
import { screenshot } from '@kit.ArkUI';

@Entry
@Component
struct Index {
  @State img\_1: image.PixelMap | undefined = undefined;
  @State img\_2: image.PixelMap | undefined = undefined;

  build() {
    Row() {
      Row() {
        Column({ space: 10 }) {
          Text('方法一：使用组件截图')
            .fontSize(20)
            .fontWeight(FontWeight.Bold);

          Text('以下是截图显示区域')
            .fontSize(10);

          Image(this.img\_1)
            .borderWidth(2)
            .width('20%')
            .height('20%')
            .backgroundColor(Color.Grey);

          Text('以下是原始图片区域')
            .fontSize(10);

          Image($r('app.media.startIcon'))
            .borderWidth(2)
            .width('30%')
            .height('30%')
            .objectFit(ImageFit.Cover)
            .id('imageForSolution');

          Button('generate UI snapshot for solution')
            .onClick(() => {
              this.getUIContext()
                .getComponentSnapshot()
                .get('imageForSolution', (error: Error, pixmap: image.PixelMap) => {
                  if (error) {
                    return;
                  }
                  this.img\_1 = pixmap;
                });
            }).margin(10);
        };
      };

      Row() {
        Column({ space: 10 }) {
          Text('方法二：使用屏幕区域截图')
            .fontSize(20)
            .fontWeight(FontWeight.Bold);

          Text('以下是截图显示区域')
            .fontSize(10);

          Image(this.img\_2)
            .borderWidth(2)
            .width('20%')
            .height('20%')
            .backgroundColor(Color.Grey);

          Text('以下是原始图片区域')
            .fontSize(10);

          Image($r('app.media.startIcon'))
            .borderWidth(2)
            .width('30%')
            .height('30%')
            .objectFit(ImageFit.Cover);

          Button('generate display snapshot for solution')
            .onClick(async () => {
              try {
                let promise = screenshot.pick();
                promise.then((pickInfo: screenshot.PickInfo) => {
                  console.info('pick Pixel bytes number: ' + pickInfo.pixelMap.getPixelBytesNumber());
                  console.info('pick Rect: ' + pickInfo.pickRect);
                  this.img\_2 = pickInfo.pixelMap;

                }).catch((err: BusinessError) => {
                  console.error(\`Failed to pick. Code: ' + Code: ${err.code}, message: ${err.message}\`);
                });
              } catch (exception) {
                console.error(\`Failed to pick Code: ' + Code: ${exception.code}, message: ${exception.message}\`);
              }
              ;
            });
        };
      };

    }
    .justifyContent(FlexAlign.SpaceAround)
    .height('100%')
    .width('100%');
  }
}

#### 常见FAQ

Q：如何查看组件截图支持的最大宽高限制？

A：可以用hdc shell hidumper -s 10 -a 'vktextureLimit'命令查看打印出来的宽高就是组件截图支持的最大宽高。

Q：如何实现截取图片中某些区域形成一个新图片？

A：对图片区域进行处理可参考[实现图片裁剪的功能](https://gitcode.com/HarmonyOS_Samples/game-puzzle)。