【前言】

我们部分场景可能会有这种诉求,将页面中的某个组件进行截图,并将截图展示出来。下面我们介绍下如何在鸿蒙next系统中实现组件截图功能。

1、注册监听组件绘制完成的事件

我们要截图,首先要等组件绘制完成后才进行,否则截出的图片可能是一片空白,实现如下,主要用到的系统接口是inspector.ComponentObserver,其中'img'是Row组件的id,这里主要监听Row组件的draw事件,表示已经绘制完成

private listener:inspector.ComponentObserver = this.getUIContext().getUIInspector().createComponentObserver('img')
this.listener.on('draw', () => {
    // todo 截取组件图片
})

build(){
Row(){
    Image($r('app.media.startIcon')).width(100).height(100)
    Image($r('app.media.startIcon')).width(100).height(100)
   }.id('img')
}

2、实现组件截图

在绘制完成的事件里面实现组件截图,代码如下,这里'img'是id,originImg的值是一个PiexelMap对象,可以直接传给Image组件展示,或者做其他操作

this.originImg = await this.getUIContext().getComponentSnapshot().get('img')

如果需要对获取的截图进行一些裁剪操作,比如高度裁剪一半,代码实现如下,这里主要用到了offscreenCanvas对象,实现图像裁剪的效果,其中screenCanvasContext.getPixelMap(0,50, viewWidth,viewHeight),0表示x轴方向不裁剪,50表示y轴方向,从50vp开始裁剪图片。

 this.originImg = await this.getUIContext().getComponentSnapshot().get('img')
 let viewInfo = this.getUIContext().getComponentUtils().getRectangleById('img')
 let viewWidth = this.getUIContext().px2vp(viewInfo.size.width)
 let viewHeight = this.getUIContext().px2vp(viewInfo.size.height)
 let screenCanvas = new OffscreenCanvas(viewWidth, viewHeight)
 let screenCanvasContext = screenCanvas.getContext('2d', new RenderingContextSettings(true))
 screenCanvasContext.drawImage(this.originImg,0,0,viewWidth,viewHeight)
 this.cropImg = screenCanvasContext.getPixelMap(0,50, viewWidth,viewHeight)

实现图片截取的效果如下:

完整的代码实现如下,这里注意下,截取组件图片时,使用了setTimeout函数,这里如果不使用的话会出现截出空白图片的情况。另外,这里的Row组件中的Image图片也可以是网络图片,这里的截图方式,即使是网络图片也能实现截图。这里之所以要做px2vp操作,是因为OffscreenCanvas接收的是vp为单位的数值,而getComponentSnapshot获取的宽高是px为单位的数值

import { inspector } from '@kit.ArkUI';

@Entry
@Component
struct DrawPage {
  @State message: string = 'Hello World';
  @State originImg:PixelMap|null = null
  @State cropImg:PixelMap|null = null
  private listener:inspector.ComponentObserver = this.getUIContext().getUIInspector().createComponentObserver('img')
  private onDrawComplete = () => {
   setTimeout(async () => {
     this.originImg = await this.getUIContext().getComponentSnapshot().get('img')
     let viewInfo = this.getUIContext().getComponentUtils().getRectangleById('img')
     let viewWidth = this.getUIContext().px2vp(viewInfo.size.width)
     let viewHeight = this.getUIContext().px2vp(viewInfo.size.height)
     let screenCanvas = new OffscreenCanvas(viewWidth, viewHeight)
     let screenCanvasContext = screenCanvas.getContext('2d', new RenderingContextSettings(true))
     screenCanvasContext.drawImage(this.originImg,0,0,viewWidth,viewHeight)
     this.cropImg = screenCanvasContext.getPixelMap(0,50, viewWidth,viewHeight)
   },500)
  }

  aboutToAppear(): void {
    this.listener.on('draw', this.onDrawComplete)
  }

  build() {
    Column() {
      Text('原始组件:')
      Row(){
        Image($r('app.media.startIcon')).width(100).height(100)
        Image($r('app.media.startIcon')).width(100).height(100)
      }.id('img')
      Column().height(20)
      Text('截取的完整图片:')
      Image(this.originImg).width(200).height(100)
      Column().height(20)
      Text('裁剪一半的图片:')
      Image(this.cropImg).width(200).height(100)
    }
    .height('100%')
    .width('100%')
  }
}

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐