HarmonyOS 鸿蒙Next开发 / ArkTS / 组件截图 / PixelMap / 长截图拼接 / UI截图
HarmonyOS 鸿蒙Next开发 / ArkTS / 组件截图 / PixelMap / 长截图拼接 / UI截图 在鸿蒙开发中,经常会遇到这样一个需求:
把多个不在同一个容器里的组件截图,按顺序拼接成一张长图。
官方示例大多是「滚动列表长截图」,但多组件静态拼接几乎没有完整范例。
下面分享一个可直接复用的多组件拼接截图方案,核心思路专注在 PixelMap 的读取与合成。
一、整体思路说明
- 逐个组件截图
- 使用
getComponentSnapshot().getSync - 拿到每个组件对应的
PixelMap
- 使用
- 读取像素数据
- 通过
readPixelsToBufferSync将像素读入ArrayBuffer - 封装为
image.PositionArea
- 通过
- 统一创建目标 PixelMap
- 高度 = 所有组件高度之和
- 宽度 = 所有组件的最大宽度
- 按顺序写入像素
- 使用
writePixelsSync - 通过
y偏移量逐段往下写,实现“拼接”
- 使用
整个过程不做 canvas 绘制、不做 bitmap 转换,完全是底层像素级拼接,性能和清晰度都很稳。
二、核心代码实现
export class SnapshotManager {
/**
* 拼接多个指定 ID 的组件为一张长图
* @param uiContext UIContext
* @param ids 组件 ID 数组(顺序即拼接顺序)
*/
static concatComponentSnapshots(
uiContext: UIContext,
ids: string[]
): image.PixelMap {
let areaArray: image.PositionArea[] = []
let totalHeight = 0
let maxWidth = 0
// 1. 逐个组件截图并读取像素
for (const id of ids) {
const pm = uiContext
.getComponentSnapshot()
.getSync(id, { waitUntilRenderFinished: true })
const info = pm.getImageInfoSync()
const bytes = pm.getPixelBytesNumber()
const buffer = new ArrayBuffer(bytes)
// 读取像素
pm.readPixelsToBufferSync(buffer)
// 封装为 PositionArea
const area: image.PositionArea = {
pixels: buffer,
offset: 0,
stride: info.size.width * 4,
region: {
x: 0,
y: 0,
size: {
width: info.size.width,
height: info.size.height
}
}
}
areaArray.push(area)
totalHeight += info.size.height
maxWidth = Math.max(maxWidth, info.size.width)
// 释放资源
pm.release()
}
// 2. 创建目标长图 PixelMap
const longPixelMap = image.createPixelMapSync({
editable: true,
pixelFormat: 4, // RGBA_8888
size: {
width: maxWidth,
height: totalHeight
}
})
// 3. 按顺序写入像素数据
let currentY = 0
for (const area of areaArray) {
const writeArea: image.PositionArea = {
pixels: area.pixels,
offset: 0,
stride: area.stride,
region: {
x: 0,
y: currentY,
size: area.region.size
}
}
longPixelMap.writePixelsSync(writeArea)
currentY += area.region.size.height
}
return longPixelMap
}
}
三、最后
需要传入截图组件的必要ID即可获得长截图后的PixelMap
更多关于HarmonyOS 鸿蒙Next开发 / ArkTS / 组件截图 / PixelMap / 长截图拼接 / UI截图的实战教程也可以访问 https://www.itying.com/category-93-b0.html
赞
更多关于HarmonyOS 鸿蒙Next开发 / ArkTS / 组件截图 / PixelMap / 长截图拼接 / UI截图的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS中,使用ArkTS的@ohos.screenshot API可实现组件截图,获取PixelMap对象。长截图拼接需通过PixelMap的readPixelsToBuffer方法读取像素数据,再使用createPixelMap合并多个PixelMap。UI截图可通过Window的getTopWindow获取窗口后调用screenshot方法完成。
这是一个非常专业且高效的解决方案,直接操作 PixelMap 进行像素级拼接,避免了不必要的渲染开销,确保了性能和图像质量。你的代码清晰地展示了 getComponentSnapshot、readPixelsToBufferSync 和 writePixelsSync 这几个核心 API 的配合使用,为处理静态多组件截图拼接需求提供了最佳实践。
方案优势分析:
- 性能优异:全程在 Native 层处理像素数据,无需经过 Canvas 或多次位图转换,内存和计算效率高。
- 保真度高:直接读写原始
PixelMap数据,避免了因格式转换可能带来的图像质量损失。 - 逻辑清晰:
PositionArea的运用准确控制了每一段组件图像的写入位置,拼接顺序精准。
关键点说明:
pixelFormat: 4对应RGBA_8888,这是最常用的格式,确保了颜色的完整性和兼容性。- 在循环中及时调用
pm.release()释放每个临时PixelMap是关键,能有效管理内存,防止泄漏。 stride的计算(width * 4)是正确的,因为RGBA_8888格式每个像素占用 4 个字节。
一个潜在优化点(非必须):
如果待拼接的组件宽度不一致,当前方案是以最大宽度创建画布,宽度较小的组件区域在拼接后其右侧区域将是透明的(Alpha通道为0)。如果需求是“紧密拼接”或需要背景色,可以在创建目标 PixelMap 后,先调用 writePixelsSync 写入一个纯色(如白色)的 PositionArea 进行填充,然后再按顺序写入组件像素。
此方案完整、可用,是解决鸿蒙应用内非滚动组件长截图拼接的推荐实现方式。

