二十四、【鸿蒙 NEXT】对组件截图
本文介绍了在鸿蒙Next系统中实现组件截图功能的方法。首先通过inspector.ComponentObserver监听目标组件的draw事件,确保组件绘制完成后再进行截图。使用getComponentSnapshot接口获取组件截图后,可以通过OffscreenCanvas对图像进行裁剪处理(如高度裁剪一半)。文中提供了完整代码示例,包括监听绘制事件、获取截图、图像裁剪等关键步骤,并指出需要注意
【前言】
我们部分场景可能会有这种诉求,将页面中的某个组件进行截图,并将截图展示出来。下面我们介绍下如何在鸿蒙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%')
}
}
更多推荐

所有评论(0)