# 18.12:屏幕截图

笔者曾经做过屏幕截图的场景:用户在 APP 上办理业务后有个签名操作,在用户签名完成后会把签名截图留存,本节笔者讲解一下如何在 OpenHarmony 实现屏幕截图功能。

# 18.12.1:使用系统 API

ArkUI 开发框架在 @ohos.screenshot 模块里提供了屏幕截图功能,它支持截取屏幕时设置截取的位置、大小,旋转角度等,但该接口为系统接口,有做系统应用的可直接使用该模块。

  • 引入模块

    import screenshot from '@ohos.screenshot';
    
    1
  • 实现截图

    public screenShot() {
      let screenshotOptions = {
      	"screenRect": {
          "left": 200,
          "top": 100,
          "width": 200,
          "height": 200
        },
      	"imageSize": {
          "width": 300,
          "height": 300
        },
        "rotation": 0,
        "displayId": 0
      };
      screenshot.save(screenshotOptions, (err, pixelMap) => {
        if (pixelMap) {
          console.log('Succeeded in saving sreenshot. Pixel bytes number: ' + pixelMap.getPixelBytesNumber());
          pixelMap.release();
        } else {
          console.log('Failed to save screenshot. Code: ' + JSON.stringify(err));
        }
      });
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

📢:以上截图能力为系统应用提供。

# 18.12.2:使用公共 API

ArkUI 开发框架在 @ohos.window 模块里给 Window 提供了 snapshot() 方法来获取当前窗口的快照,它返回一个 PixelMap,因此我们也可以使用该方法获取屏幕截图。

  • 获取 Window 对象

    UIAbilityonWindowStageCreate() 方法是加载页面的入口,它对外提供一个 WindowStage 对象,该对象可以获取当前 Window, 然后把获取到的 Window 存储在 globalThis 中方便后续使用,代码如下:

    onWindowStageCreate(windowStage: Window.WindowStage) {
    
      // 获取到 Window 后保存在 globalThis 中
      var mainWindow = windowStage.getMainWindowSync();
      globalThis.mainWindow = mainWindow;
    
      windowStage.loadContent("pages/Index", (err, data) => {
        // ……
      });
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
  • 实现屏幕截图

    有了 Window 对象后,就可以调用它的 snapshot() 方法了,代码如下所示:

    private snapshot() {
      var window = globalThis.mainWindow as Window.Window;
      window.snapshot((error, image) => {
        if (image) {
          console.log("snapshot success");
        } else {
          console.log("snapshot failure: " + JSON.stringify(error));
        }
      });
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
  • 完整样例

    import Window from '@ohos.window'
    
    @Entry @Component struct ArkUIClubScreenShotTest {
    
      @State image: PixelMap = undefined;
    
      build() {
        Column() {
          Image(this.image)
            .width(120)
            .height(120)
            .objectFit(ImageFit.ScaleDown)
            .backgroundColor(Color.Pink)
    
          Button("shotcut")
            .fontSize(50)
            .fontWeight(FontWeight.Bold)
            .onClick(() => {
              this.snapshot();
            })
        }
        .width('100%')
        .height('100%')
        .backgroundColor("#aabbcc")
      }
    
      private snapshot() {
        var window = globalThis.mainWindow as Window.Window;
        window.snapshot((error, image) => {
          if (image) {
            this.image = image;
            console.log("snapshot success");
          } else {
            console.log("snapshot failure: " + JSON.stringify(error));
          }
        });
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38

    样例运行结果如下图所示:

    18_12_2_1

    📢:该方式获取的截图不包含状态栏和导航栏。

# 18.12.3:获取部分截图

拿到屏幕截图 PixelMap 后,如果想获取其中一部分截图,可以使用 PixelMapcrop() 方法,样例代码如下所示:

private cropPixelMap(image: image.PixelMap, x: number, y: number, width: number, height: number) {
  image.crop({
    x: x,
    y: y,
    size: {
      width: width,
      height: height
    }
  }).then(() => {
    console.log("crop image success");
  }).catch((error) => {
    console.log("crop image failure: " + JSON.stringify(error));
  })
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

📢:PixelMap 提供了众多图片操作相关的 API,读者可自行查看文档。

# 18.12.4:对组件截图

对组件进行截图,也就是需要获取到目标组件的位置和尺寸,然后把截取的 PixelMap 进行剪切即可。

  • 获取组件属性

    ArkUI 开发框架提供了一个全局方法 getInspectorByKey(),它返回指定 id 组件的属性信息,比如组件在屏幕上的宽高、位置等信息,样例代码如下所示:

    Button("区域截图")
      .width(220)
      .height(50)
      .id(this.screenshotWidgetID)                     // 给组件添加 id 属性
      .onClick(() => {
        this.parseWidgetRect(this.screenshotWidgetID); // 获取指定 id 控件的属性
      })
    
    private parseWidgetRect(id: string) {
      var attributes = getInspectorByKey(id);
      console.log(attributes);
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    点击 Button 执行 parseWidgetRect() 方法,该方法打印指定 id 控件的属性信息,打印部分属性信息如下所示:

    {
    	"$type": "Button",
    	"$ID": 19,
    	"$rect": "[195.00, 435.00][525.00,510.00]",
    	"$attrs": {
    		"margin": "0.00px",
    		"padding": "0.00px",
    		"height": "50.00vp",
    		"width": "220.00vp",
    		"size": {
    			"width": "220.00vp",
    			"height": "50.00vp"
    		},
    		"label": "区域截图",
    	}
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
  • 完整样例演示

    import image from '@ohos.multimedia.image';
    import Window from '@ohos.window'
    
    @Entry @Component struct ArkUIClubScreenShotTest {
    
      @State image: PixelMap = undefined;
    
      private screenshotWidgetID = "screenshot_button_id";
    
      build() {
        Column({space: 10}) {
          Image(this.image)
            .width(220)
            .height(220)
            .objectFit(ImageFit.ScaleDown)
            .backgroundColor(Color.Pink)
    
          Button("屏幕截图")
            .width(220)
            .height(50)
            .fontWeight(FontWeight.Bold)
            .onClick(() => {
              this.screenShot();
            })
    
          Button("区域截图")
            .width(220)
            .height(50)
            .id(this.screenshotWidgetID)
            .onClick(() => {
              this.snapshot();
            })
        }
        .width('100%')
        .height('100%')
        .backgroundColor("#aabbcc")
      }
    
      private getWidgetRect(id: string): Array<number> {
        var attrs  = getInspectorByKey(id);
        var info   = "[" + JSON.parse(attrs.split("$").join("")).rect + "]";
        var rect   = JSON.parse(info);
        var left   = Number(rect[0][0]);
        var top    = Number(rect[0][1]);
        var right  = Number(rect[1][0]);
        var bottom = Number(rect[1][1]);
        console.log("left: " + left + ", top: " + top + ", right: " + right + ", bottom: " + bottom);
        return [left, top, right, bottom];
      }
    
      private snapshot() {
        var window = globalThis.mainWindow as Window.Window;
        window.snapshot((error, image) => {
          if (image) {
            console.log("snapshot success");
            var rect = this.getWidgetRect(this.screenshotWidgetID);
            this.cropPixelMap(image, rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1]);
          } else {
            console.log("snapshot failure: " + JSON.stringify(error));
          }
        });
      }
    
      private screenShot() {
        var window = globalThis.mainWindow as Window.Window;
        window.snapshot((error, image) => {
          if (image) {
            this.image = image;
            console.log("snapshot success");
          } else {
            console.log("snapshot failure: " + JSON.stringify(error));
          }
        });
      }
    
      private cropPixelMap(image: image.PixelMap, x: number, y: number, width: number, height: number) {
        image.crop({
          x: x,
          y: y,
          size: {
            width: width,
            height: height
          }
        }).then(() => {
          this.image = image;
        }).catch((error) => {
          console.log("crop image failure: " + JSON.stringify(error));
        })
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90

    样例运行结果如下图所示:

    18_12_4_1
    (adsbygoogle = window.adsbygoogle || []).push({});
请作者喝杯咖啡

津公网安备 12011402001367号

津ICP备2020008934号-2

中央网信办互联网违法和不良信息举报中心

天津市互联网违法和不良信息举报中心