三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

鸿蒙6.1 arkui.componentSnapshot组件截图坑:返回PixelMap不是dataURL

鸿蒙6.1 arkui.componentSnapshot组件截图坑:返回PixelMap不是dataURL

本文是「鸿蒙 6.1 API 23 开发坑系列」第 2 篇(ArkUI 桶第 2 篇)。本篇讲@ohos.arkui.componentSnapshotnamespace(API 10+,鸿蒙 6.1 API 23 基座)——组件截图三个方法get/getSync/createFromBuilder鸿蒙坑根因:①import坑——import { componentSnapshot } from编译错(has no exported member),必须import componentSnapshot from(default import);② 返回值坑——get(id)返回Promise<image.PixelMap>不是dataURL字符串(React html2canvas 返回 dataURL),image.PixelMap是像素图有getImageInfo/getPixelBytes可读像素;③createFromBuilder(builder)的 builder 参数是CustomBuilder@Builder装饰的函数)不是 Component。

一、开篇:鸿蒙 componentSnapshot 不是 html2canvas,是「返回 PixelMap 像素图」

你写 React 时,组件截图用html2canvas(返回 canvas → toDataURL 转 dataURL 字符串):

// React html2canvas:返回 canvas → toDataURL 转 dataURL 字符串 async function snapshotComponent() { // ❌ html2canvas 返回 HTMLCanvasElement,toDataURL() 转 dataURL 字符串 const canvas: HTMLCanvasElement = await html2canvas(document.getElementById('target')) const dataURL: string = canvas.toDataURL('image/jpeg', 0.9) // ❌ dataURL 字符串 // ❌ React html2canvas:返回 canvas → dataURL 字符串,不是 PixelMap 像素图 }

你写鸿蒙 ArkTS 时,组件截图用componentSnapshot.get(id)(返回Promise<image.PixelMap>像素图):

// ArkTS componentSnapshot:返回 Promise<image.PixelMap> 像素图,不是 dataURL 字符串 import componentSnapshot from '@ohos.arkui.componentSnapshot' // ✅ default import import image from '@ohos.multimedia.image' async function snapshotComponent() { // ✅ get(id) 返回 Promise<image.PixelMap>,image.PixelMap 是像素图不是 dataURL const pixelMap: image.PixelMap = await componentSnapshot.get('snapshotTarget') const imageInfo: image.ImageInfo = await pixelMap.getImageInfo() // ✅ PixelMap 有 getImageInfo/getPixelBytes 可读像素,不是 dataURL 字符串 const width: number = imageInfo.size.width const height: number = imageInfo.size.height }

React html2canvas vs 鸿蒙 componentSnapshot 的区别:React 把组件截图当 canvas 转 dataURL(html2canvas 返回 HTMLCanvasElement + toDataURL() 转 dataURL 字符串,base64 编码字符串),ArkTS 把组件截图当 PixelMap 像素图(componentSnapshot.get 返回 Promise<image.PixelMap>,image.PixelMap 是像素图有 getImageInfo/getPixelBytes 可读像素,不是 dataURL 字符串)。根因不是 dataURL 字符串是 PixelMap 像素图——鸿蒙返回 image.PixelMap 像素图,有 getImageInfo/getPixelBytes 可读像素。

二、根因:鸿蒙 componentSnapshot 的三个绑定机制

鸿蒙@ohos.arkui.componentSnapshotnamespace(API 10+)有三个截图方法,每个返回image.PixelMap像素图。绑定机制来自三重根因。

机制 1:import 坑——default import 不是 named import

鸿蒙坑根因:import { componentSnapshot } from编译错——必须import componentSnapshot from

// ❌ 鸿蒙坑:import { componentSnapshot } from 编译错(has no exported member) // ❌ 编译错:Module '"@ohos.arkui.componentSnapshot"' has no exported member 'componentSnapshot' // ❌ 错误信息:Did you mean to use 'import componentSnapshot from "@ohos.arkui.componentSnapshot"' instead? import { componentSnapshot } from '@ohos.arkui.componentSnapshot' // ❌ named import 编译错 // ✅ 正确用法:default import(componentSnapshot 是 default export 不是 named export) import componentSnapshot from '@ohos.arkui.componentSnapshot' // ✅ default import // 鸿蒙坑根因:componentSnapshot 是 default export,必须 default import 不是 named import

import 坑根因@ohos.arkui.componentSnapshotcomponentSnapshotdeclare namespace(default namespace export),不是 named export,所以import { componentSnapshot }触发has no exported member 'componentSnapshot'编译错。正确用法是import componentSnapshot from(default import)。

机制 2:get 返回 Promise<image.PixelMap> 不是 dataURL 字符串

鸿蒙坑根因:get(id)返回Promise<image.PixelMap>像素图,不是 dataURL 字符串:

// ✅ get(id): Promise<image.PixelMap> 异步截图(返回 Promise<image.PixelMap>,不是 dataURL) import componentSnapshot from '@ohos.arkui.componentSnapshot' import image from '@ohos.multimedia.image' async function asyncSnapshot() { // ✅ get(id) 返回 Promise<image.PixelMap>,image.PixelMap 是像素图不是 dataURL const pixelMap: image.PixelMap = await componentSnapshot.get('snapshotTarget') // ✅ PixelMap 有 getImageInfo/getPixelBytes 可读像素 const imageInfo: image.ImageInfo = await pixelMap.getImageInfo() const width: number = imageInfo.size.width const height: number = imageInfo.size.height // 鸿蒙坑根因:get 返回 Promise<image.PixelMap> 像素图,React html2canvas 返回 dataURL 字符串 } // ✅ getSync(id): image.PixelMap 同步截图(API 12+,直接返回不用 await) function syncSnapshot() { // ✅ getSync 是 API 12+ 同步方法,直接返回 image.PixelMap 不用 await const pixelMap: image.PixelMap = componentSnapshot.getSync('snapshotTarget') // 鸿蒙坑:getSync 是 API 12+ 同步方法,不是 Promise 不用 await }

get vs getSync 的区别get(id): Promise<image.PixelMap>异步截图(API 10+,返回 Promise 需要 await),getSync(id): image.PixelMap同步截图(API 12+,直接返回 image.PixelMap 不用 await,不是 Promise)。鸿蒙坑:getSync 是 API 12+ 同步方法,不是 Promise 不用 await,直接返回 image.PixelMap。

image.PixelMap vs dataURL 的区别image.PixelMap是鸿蒙像素图接口(有 getImageInfo/getPixelBytes 可读像素,release 释放资源),dataURL是 base64 编码字符串(React html2canvas 返回,无 getImageInfo/getPixelBytes)。根因不是 dataURL 字符串是 PixelMap 像素图——鸿蒙返回 image.PixelMap 像素图,有 getImageInfo/getPixelBytes 可读像素。

机制 3:createFromBuilder(builder) 的 builder 参数是 CustomBuilder 不是 Component

鸿蒙坑根因:createFromBuilder(builder)的 builder 参数是CustomBuilder@Builder装饰的函数),不是 Component:

// ✅ createFromBuilder(builder) 从 CustomBuilder 截图(builder 参数是 @Builder 函数不是 Component) import componentSnapshot from '@ohos.arkui.componentSnapshot' // ✅ @Builder 装饰的函数是 CustomBuilder 类型(createFromBuilder 的 builder 参数) @Builder function MySnapshotBuilder() { Column({ space: 4 }) { Text('CustomBuilder 截图内容').fontSize(14).fontColor('#28a745') } .padding(12).backgroundColor('#d4edda').borderRadius(8) } async function builderSnapshot() { // ✅ createFromBuilder(builder) 返回 Promise<image.PixelMap> // ✅ 鸿蒙坑:builder 参数是 CustomBuilder(@Builder 函数),不是 Component const pixelMap: image.PixelMap = await componentSnapshot.createFromBuilder(MySnapshotBuilder) // 鸿蒙坑根因:builder 参数是 CustomBuilder(@Builder 装饰的函数),不是 Component }

createFromBuilder 的 builder 参数坑createFromBuilder(builder: CustomBuilder, ...)的 builder 参数是CustomBuilder类型(@Builder装饰的函数引用,不是 Component 实例,不是 build() 返回值)。鸿蒙坑:传 Component 实例或 build() 返回值会类型错——必须传@Builder装饰的函数引用(MySnapshotBuilder不是MySnapshotBuilder())。

三、真机配图:鸿蒙 arkui.componentSnapshot 组件截图坑——get/getSync/createFromBuilder

真机配图展示鸿蒙 arkui.componentSnapshot 组件截图坑:

  • 初始态:鸿蒙 6.1 arkui.componentSnapshot 组件截图坑标题,截图目标组件(红框 id=snapshotTarget,四角文字左上/右上/左下/右下),场景1~4 卡片(get/getSync/createFromBuilder/截图存文件),要点说明
  • get(id) 异步截图态:点击「① get(id) 异步截图」按钮,snapshotStatus 显示「✅ componentSnapshot.get(id) 异步截图成功:PixelMap 1066x278」,截图次数 1——get 返回 Promise<image.PixelMap> 验证
  • getSync(id) 同步截图态:点击「② getSync(id) 同步截图」按钮,syncSnapshotStatus 显示「✅ componentSnapshot.getSync(id) 同步截图成功:返回 image.PixelMap(不用 await)」,截图次数 2——getSync 同步返回 image.PixelMap 验证
  • createFromBuilder 态:点击「③ createFromBuilder 截图」按钮,builderSnapshotStatus 显示「✅ createFromBuilder(builder) 截图成功:PixelMap 393x78」,截图次数 3——createFromBuilder 从 CustomBuilder 截图验证
  • 截图存文件态:点击「⑦ 截图存文件」按钮,savedFilePath 显示「/data/storage/…/cache/snapshot_*.jpeg」,截图次数 4——PixelMap 存文件验证(image.createImagePacker + fs.writeSync)

四、真解法:鸿蒙 componentSnapshot 的三个场景

场景 1:get(id) 异步截图 + getSync(id) 同步截图——90% 场景首选

get/getSync 截图用componentSnapshot.get('id')+componentSnapshot.getSync('id')

// ✅ 场景 1:get(id) 异步截图 + getSync(id) 同步截图(API 10/12,90% 场景首选) import componentSnapshot from '@ohos.arkui.componentSnapshot' // ✅ default import import image from '@ohos.multimedia.image' // ✅ get(id): Promise<image.PixelMap> 异步截图(API 10+,返回 Promise 需要 await) async function asyncSnapshot() { const pixelMap: image.PixelMap = await componentSnapshot.get('snapshotTarget') const imageInfo: image.ImageInfo = await pixelMap.getImageInfo() // PixelMap 像素图:getImageInfo 读尺寸,getPixelBytes 读像素 } // ✅ getSync(id): image.PixelMap 同步截图(API 12+,直接返回不用 await) function syncSnapshot() { const pixelMap: image.PixelMap = componentSnapshot.getSync('snapshotTarget') // getSync 同步返回 image.PixelMap,不是 Promise 不用 await } // get/getSync 截图:90% 场景首选,返回 image.PixelMap 像素图不是 dataURL

鸿蒙 componentSnapshot API 真名坑import componentSnapshot from '@ohos.arkui.componentSnapshot'(default import 不是 named import);get(id: string, callback?: AsyncCallback<image.PixelMap>, options?: SnapshotOptions): void异步截图(API 10+,callback 可选);get(id: string, options?: SnapshotOptions): Promise<image.PixelMap>Promise 异步截图(API 10+,返回 Promise<image.PixelMap>);getSync(id: string, options?: SnapshotOptions): image.PixelMap同步截图(API 12+,直接返回 image.PixelMap);image.PixelMap像素图接口(getImageInfo/getPixelBytes/release);SysCapSystemCapability.ArkUI.ArkUI.Full@crossplatform跨平台;@atomicservice原子化服务;SnapshotOptions(API 15+,SnapshotRegion/left/right/top/bottom 矩形区域截图)。

场景 2:createFromBuilder(builder) 从 CustomBuilder 截图

createFromBuilder 截图用componentSnapshot.createFromBuilder(MyBuilder)+@Builder装饰函数:

// ✅ 场景 2:createFromBuilder(builder) 从 CustomBuilder 截图(API 10) import componentSnapshot from '@ohos.arkui.componentSnapshot' // ✅ @Builder 装饰的函数是 CustomBuilder 类型(createFromBuilder 的 builder 参数) @Builder function MySnapshotBuilder() { Column({ space: 4 }) { Text('CustomBuilder 截图内容').fontSize(14).fontColor('#28a745').fontWeight(FontWeight.Bold) Text('createFromBuilder 从 Builder 截图').fontSize(10).fontColor('#888') } .padding(12).backgroundColor('#d4edda').borderRadius(8) } async function builderSnapshot() { // ✅ createFromBuilder(builder) 返回 Promise<image.PixelMap> // ✅ 鸿蒙坑:builder 参数是 CustomBuilder(@Builder 函数引用),不是 Component 实例 const pixelMap: image.PixelMap = await componentSnapshot.createFromBuilder(MySnapshotBuilder) // ✅ createFromBuilder 也有 callback 和 delay/checkImageStatus/options 参数 // componentSnapshot.createFromBuilder(MyBuilder, 500, true, options) // delay=500ms, checkImageStatus=true } // createFromBuilder 从 CustomBuilder 截图:builder 参数是 @Builder 函数引用不是 Component

鸿蒙 createFromBuilder API 真名坑createFromBuilder(builder: CustomBuilder, callback?: AsyncCallback<image.PixelMap>, delay?: number, checkImageStatus?: boolean, options?: SnapshotOptions): voidcallback 异步(API 10+);createFromBuilder(builder: CustomBuilder, delay?: number, checkImageStatus?: boolean, options?: SnapshotOptions): Promise<image.PixelMap>Promise 异步(API 10+);CustomBuilder@Builder装饰的函数类型(传函数引用MyBuilder不是调用MyBuilder());delay延迟截图毫秒数(等组件渲染完);checkImageStatus检查图片状态(true 等图片加载完再截图);鸿蒙坑:builder 参数传 Component 实例或 build() 返回值会类型错——必须传@Builder装饰的函数引用。

场景 3:PixelMap 存文件——image.createImagePacker + fs.writeSync

PixelMap 存文件用image.createImagePacker().packing()打包 JPEG buffer +fs.writeSync写文件:

// ✅ 场景 3:PixelMap 存文件——image.createImagePacker + fs.writeSync(API 10) import componentSnapshot from '@ohos.arkui.componentSnapshot' import image from '@ohos.multimedia.image' import fs from '@ohos.file.fs' async function snapshotAndSave() { // ✅ get(id) 截图返回 PixelMap const pixelMap: image.PixelMap = await componentSnapshot.get('snapshotTarget') // ✅ image.createImagePacker() 打包 PixelMap 为 JPEG buffer const imagePacker: image.ImagePacker = image.createImagePacker() const jpegBuffer: ArrayBuffer = await imagePacker.packing(pixelMap, { format: 'image/jpeg', // ✅ format: 'image/jpeg' 不是 'jpeg' quality: 90 // ✅ quality: 0-100 }) imagePacker.release() // ✅ release 释放 ImagePacker // ✅ fs.openSync 打开文件 + fs.writeSync 写 buffer + fs.closeSync 关文件 const context = getContext(this) // ✅ getContext 获取 Context(@deprecated 警告但仍可用) const cacheDir: string = context.cacheDir // ✅ cacheDir 缓存目录 const filePath: string = cacheDir + '/snapshot_' + Date.now() + '.jpeg' const fileFd: number = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.WRITE_ONLY).fd // ✅ .fd 取文件描述符 fs.writeSync(fileFd, jpegBuffer) // ✅ writeSync(fd, buffer) 第一参传 fd fs.closeSync(fileFd) // ✅ closeSync(fd) 关文件 } // PixelMap 存文件:image.createImagePacker().packing JPEG buffer + fs.writeSync(fd, buffer)

鸿蒙 PixelMap 存文件 API 真名坑image.createImagePacker(): image.ImagePacker创建打包器(API 10+);imagePacker.packing(pixelMap, options?: image.PackingOption): Promise<ArrayBuffer>打包 PixelMap 为 buffer(API 10+);PackingOption{ format: 'image/jpeg', quality: 90 }(format 是'image/jpeg'不是'jpeg',quality 0-100);imagePacker.release()释放打包器;fs.openSync(path, mode): fs.File同步打开文件(API 10+,.fd取文件描述符);fs.writeSync(fd: number, buffer: ArrayBuffer)同步写 buffer(API 10+,第一参传 fd 文件描述符,不是 File 实例);fs.closeSync(fd: number)同步关文件;鸿蒙坑fs.writeSync第一参传file.fd文件描述符(不是 File 实例方法,是 namespace 顶层函数);getContext(this)已 @deprecated 警告但仍可用(推荐用this.getContext()或组件 Context)。

五、一句话哲学

写鸿蒙 ArkUI 记住:componentSnapshot 不是 html2canvas 是「返回 image.PixelMap 像素图」——鸿蒙 6.1 API 23@ohos.arkui.componentSnapshotnamespace(API 10+,鸿蒙 6.1 API 23 基座,SysCap SystemCapability.ArkUI.ArkUI.Full,@crossplatform @atomicservice)。根因不是 dataURL 字符串是 PixelMap 像素图——import componentSnapshot from(✅ default import,❌import { componentSnapshot } from编译错has no exported member),get(id): Promise<image.PixelMap>异步截图(API 10+,返回 Promise<image.PixelMap> 像素图不是 dataURL 字符串,image.PixelMap 有 getImageInfo/getPixelBytes/release 可读像素),getSync(id): image.PixelMap同步截图(API 12+,直接返回 image.PixelMap 不用 await 不是 Promise),createFromBuilder(builder: CustomBuilder): Promise<image.PixelMap>从 CustomBuilder 截图(builder 参数是@Builder装饰的函数引用不是 Component 实例,有 delay/checkImageStatus/options 参数),image.createImagePacker().packing(pixelMap, { format: 'image/jpeg', quality: 90 })打包 PixelMap 为 JPEG buffer(format 是'image/jpeg'不是'jpeg'),fs.writeSync(fd, buffer)写文件(第一参传file.fd文件描述符,是 namespace 顶层函数不是 File 实例方法)。componentSnapshot 返回 image.PixelMap 像素图不是 dataURL 字符串是鸿蒙 6.1 arkui.componentSnapshot 组件截图坑核心!

能力系列回链

  • 鸿蒙 7.0 新特性篇 1~17(沉浸式毛玻璃/Component3D/智能体框架/方舟引擎/星盾安全/星河互联/空间音频/可变字体/游戏快启/分布式数据盾/LTPO 可变帧率/AI 文档识别/多形态服务窗口/AI 反诈/机密计算/空间计算/小艺全面进化)
  • 鸿蒙 6.1 API 23 开发坑系列篇 1「ArkUI.modifier 装饰器坑」——attributeModifier + AttributeModifier 状态化节点修改器
  • 鸿蒙 6.1 API 23 开发坑系列篇 2「arkui.componentSnapshot 组件截图坑」——get/getSync/createFromBuilder 返回 image.PixelMap(本文)

真机 demo 完整代码

// 鸿蒙 6.1 API 23 开发坑系列篇 2:arkui.componentSnapshot 组件截图坑——get/getSync/createFromBuilder 返回 image.PixelMap 根因 import componentSnapshot from '@ohos.arkui.componentSnapshot' import image from '@ohos.multimedia.image' import fs from '@ohos.file.fs' @Builder function MySnapshotBuilder() { Column({ space: 4 }) { Text('CustomBuilder 截图内容').fontSize(14).fontColor('#28a745').fontWeight(FontWeight.Bold) Text('createFromBuilder 从 Builder 截图').fontSize(10).fontColor('#888') } .padding(12) .backgroundColor('#d4edda') .borderRadius(8) } @Entry @Component struct Index { @State log: string = '(未操作)' @State snapshotStatus: string = '(未截)' @State syncSnapshotStatus: string = '(未截)' @State builderSnapshotStatus: string = '(未截)' @State pixelMapWidth: number = 0 @State pixelMapHeight: number = 0 @State snapshotCount: number = 0 @State savedFilePath: string = '(未存)' @State lastError: string = '(无错)' aboutToAppear() { this.log = '鸿蒙 6.1 arkui.componentSnapshot 组件截图坑:get/getSync/createFromBuilder 返回 image.PixelMap' } async demonstrateAsyncSnapshot() { try { const pixelMap: image.PixelMap = await componentSnapshot.get('snapshotTarget') const imageInfo: image.ImageInfo = await pixelMap.getImageInfo() this.pixelMapWidth = imageInfo.size.width this.pixelMapHeight = imageInfo.size.height this.snapshotStatus = '✅ componentSnapshot.get(id) 异步截图成功:PixelMap ' + this.pixelMapWidth + 'x' + this.pixelMapHeight this.log = '✅ get(id) 返回 Promise<image.PixelMap>(不是 dataURL),PixelMap 像素图 ' + this.pixelMapWidth + 'x' + this.pixelMapHeight this.snapshotCount++ this.lastError = '(无错)' } catch (e) { this.lastError = '❌ get 异步截图错:' + e.message } } demonstrateSyncSnapshot() { try { const pixelMap: image.PixelMap = componentSnapshot.getSync('snapshotTarget') this.syncSnapshotStatus = '✅ componentSnapshot.getSync(id) 同步截图成功:返回 image.PixelMap(不用 await)' this.snapshotCount++ this.lastError = '(无错)' } catch (e) { this.lastError = '❌ getSync 同步截图错:' + e.message } } async demonstrateBuilderSnapshot() { try { const pixelMap: image.PixelMap = await componentSnapshot.createFromBuilder(MySnapshotBuilder) const imageInfo: image.ImageInfo = await pixelMap.getImageInfo() this.builderSnapshotStatus = '✅ createFromBuilder(builder) 截图成功:PixelMap ' + imageInfo.size.width + 'x' + imageInfo.size.height this.snapshotCount++ this.lastError = '(无错)' } catch (e) { this.lastError = '❌ createFromBuilder 截图错:' + e.message } } async savePixelMapToFile(pixelMap: image.PixelMap): Promise<string> { try { const imagePacker: image.ImagePacker = image.createImagePacker() const jpegBuffer: ArrayBuffer = await imagePacker.packing(pixelMap, { format: 'image/jpeg', quality: 90 }) imagePacker.release() const context = getContext(this) const cacheDir: string = context.cacheDir const filePath: string = cacheDir + '/snapshot_' + Date.now() + '.jpeg' const fileFd: number = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.WRITE_ONLY).fd fs.writeSync(fileFd, jpegBuffer) fs.closeSync(fileFd) return filePath } catch (e) { this.lastError = '❌ savePixelMapToFile 错:' + e.message return '(存文件失败)' } } async demonstrateSnapshotAndSave() { try { const pixelMap: image.PixelMap = await componentSnapshot.get('snapshotTarget') const filePath: string = await this.savePixelMapToFile(pixelMap) this.savedFilePath = filePath this.log = '✅ get(id) 截图 + image.createImagePacker() 打包 JPEG + fs.writeSync 存文件:' + filePath this.snapshotCount++ this.lastError = '(无错)' } catch (e) { this.lastError = '❌ 截图存文件错:' + e.message } } build() { Column({ space: 8 }) { Text('鸿蒙 6.1 arkui.componentSnapshot 组件截图坑') .fontSize(18).fontWeight(FontWeight.Bold).margin({ top: 16, bottom: 4 }) Text('get/getSync/createFromBuilder 返回 image.PixelMap 根因') .fontSize(11).fontColor('#888').margin({ bottom: 8 }) Column({ space: 4 }) { Text('截图目标组件(id=snapshotTarget)').fontSize(12).fontColor('#dc3545').fontWeight(FontWeight.Bold) Text('componentSnapshot.get("snapshotTarget") 截这个 Column').fontSize(9).fontColor('#888') Row({ space: 8 }) { Text('左上').fontSize(10).fontColor('#2563eb') Text('右上').fontSize(10).fontColor('#ff6600') } Row({ space: 8 }) { Text('左下').fontSize(10).fontColor('#28a745') Text('右下').fontSize(10).fontColor('#ffc107') } } .id('snapshotTarget') .width('80%') .padding(12) .backgroundColor('#f8d7da') .borderRadius(8) .border({ width: 2, color: '#dc3545' }) Column({ space: 6 }) { Text('场景 1:componentSnapshot.get(id) 异步截图(API 10,返回 Promise<image.PixelMap>)') .fontSize(12).fontColor('#2563eb').fontWeight(FontWeight.Bold) Text('get 是 async 返回 Promise<image.PixelMap>,不是 sync 返回 dataURL 字符串') .fontSize(9).fontColor('#888') Button('① get(id) 异步截图').height(30).fontSize(9).backgroundColor('#2563eb20') .onClick(() => this.demonstrateAsyncSnapshot()) Text(this.snapshotStatus).fontSize(9).fontColor('#2563eb').margin({ top: 4 }) Text(`PixelMap 尺寸:${this.pixelMapWidth}x${this.pixelMapHeight}`).fontSize(8).fontColor('#2563eb').margin({ top: 2 }) } .width('92%').padding(8).backgroundColor('#e0f0ff').borderRadius(8) Column({ space: 6 }) { Text('场景 2:componentSnapshot.getSync(id) 同步截图(API 12,返回 image.PixelMap)') .fontSize(12).fontColor('#ff6600').fontWeight(FontWeight.Bold) Text('getSync 是 API 12+ 同步方法,直接返回 image.PixelMap 不用 await') .fontSize(9).fontColor('#888') Button('② getSync(id) 同步截图').height(30).fontSize(9).backgroundColor('#ff660020') .onClick(() => this.demonstrateSyncSnapshot()) Text(this.syncSnapshotStatus).fontSize(9).fontColor('#ff6600').margin({ top: 4 }) } .width('92%').padding(8).backgroundColor('#fff3e0').borderRadius(8) Column({ space: 6 }) { Text('场景 3:createFromBuilder(builder) 从 CustomBuilder 截图(API 10)') .fontSize(12).fontColor('#28a745').fontWeight(FontWeight.Bold) Text('builder 参数是 CustomBuilder 类型(@Builder 装饰的函数),不是 Component') .fontSize(9).fontColor('#888') Button('③ createFromBuilder 截图').height(30).fontSize(9).backgroundColor('#28a74520') .onClick(() => this.demonstrateBuilderSnapshot()) Text(this.builderSnapshotStatus).fontSize(9).fontColor('#28a745').margin({ top: 4 }) } .width('92%').padding(8).backgroundColor('#d4edda').borderRadius(8) Column({ space: 6 }) { Text('场景 4:截图 + 存文件(image.createImagePacker + fs.writeSync)') .fontSize(12).fontColor('#dc3545').fontWeight(FontWeight.Bold) Text('PixelMap → image.createImagePacker().packing JPEG buffer → fs.writeSync 存文件') .fontSize(9).fontColor('#888') Button('⑦ 截图存文件').height(30).fontSize(9).backgroundColor('#dc354520') .onClick(() => this.demonstrateSnapshotAndSave()) Text(`存文件路径:${this.savedFilePath}`).fontSize(8).fontColor('#dc3545').margin({ top: 4 }) } .width('92%').padding(8).backgroundColor('#f8d7da').borderRadius(8) Column({ space: 3 }) { Text('鸿蒙 6.1 arkui.componentSnapshot 组件截图坑要点') .fontSize(10).fontColor('#6c757d').fontWeight(FontWeight.Bold) Text('① @ohos.arkui.componentSnapshot namespace API 10+(鸿蒙 6.1 API 23 基座)') .fontSize(8).fontColor('#2563eb') Text('② get(id): Promise<image.PixelMap> 异步截图(返回 Promise<image.PixelMap> 不是 dataURL)') .fontSize(8).fontColor('#ff6600') Text('③ getSync(id): image.PixelMap 同步截图(API 12+,直接返回不用 await)') .fontSize(8).fontColor('#28a745') Text('④ createFromBuilder(builder): Promise<image.PixelMap> 从 CustomBuilder 截图') .fontSize(8).fontColor('#dc3545') Text('⑤ 鸿蒙坑:get 返回 Promise<image.PixelMap>,React html2canvas 返回 dataURL 字符串') .fontSize(8).fontColor('#dc3545') Text('⑥ image.PixelMap 是像素图不是 dataURL——有 getImageInfo/getPixelBytes 可读像素') .fontSize(8).fontColor('#2563eb') Text('⑦ PixelMap 存文件:image.createImagePacker().packing(buffer) + fs.writeSync(fd, buffer)') .fontSize(8).fontColor('#ff6600') Text('⑧ createFromBuilder 的 builder 参数是 CustomBuilder(@Builder 函数),不是 Component') .fontSize(8).fontColor('#28a745') Text('⑨ SnapshotOptions(API 15+):SnapshotRegion/left/right/top/bottom 矩形区域截图') .fontSize(8).fontColor('#6c757d') Text('⑩ React 对比:componentSnapshot 不是 html2canvas——鸿蒙返回 PixelMap 像素图不是 dataURL') .fontSize(8).fontColor('#17a2b8') } .width('92%').padding(6).backgroundColor('#f8f9fa').borderRadius(8) Row({ space: 12 }) { Text(`截图次数: ${this.snapshotCount}`).fontSize(9).fontColor('#28a745') Text(`PixelMap: ${this.pixelMapWidth}x${this.pixelMapHeight}`).fontSize(9).fontColor('#2563eb') } .margin({ top: 6 }) Text(`日志:${this.log}`).fontSize(9).fontColor('#333').margin({ top: 6 }) Text(`错误:${this.lastError}`).fontSize(8).fontColor('#dc3545').margin({ top: 2 }) Text('鸿蒙 6.1(API 10+)arkui.componentSnapshot:get/getSync/createFromBuilder 返回 image.PixelMap 像素图') .fontSize(8).fontColor('#6c757d').margin({ top: 6 }) } .width('100%').height('100%').alignItems(HorizontalAlign.Center) } }

写鸿蒙 ArkUI 记住:componentSnapshot 不是 html2canvas 是「返回 image.PixelMap 像素图」——鸿蒙 6.1 API 23@ohos.arkui.componentSnapshotnamespace(API 10+,鸿蒙 6.1 API 23 基座,SysCap SystemCapability.ArkUI.ArkUI.Full,@crossplatform @atomicservice)。根因不是 dataURL 字符串是 PixelMap 像素图——import componentSnapshot from(✅ default import,❌import { componentSnapshot } from编译错has no exported member),get(id): Promise<image.PixelMap>异步截图(API 10+,返回 Promise<image.PixelMap> 像素图不是 dataURL 字符串,image.PixelMap 有 getImageInfo/getPixelBytes/release 可读像素),getSync(id): image.PixelMap同步截图(API 12+,直接返回 image.PixelMap 不用 await 不是 Promise),createFromBuilder(builder: CustomBuilder): Promise<image.PixelMap>从 CustomBuilder 截图(builder 参数是@Builder装饰的函数引用不是 Component 实例,有 delay/checkImageStatus/options 参数),image.createImagePacker().packing(pixelMap, { format: 'image/jpeg', quality: 90 })打包 PixelMap 为 JPEG buffer(format 是'image/jpeg'不是'jpeg'),fs.writeSync(fd, buffer)写文件(第一参传file.fd文件描述符,是 namespace 顶层函数不是 File 实例方法)。componentSnapshot 返回 image.PixelMap 像素图不是 dataURL 字符串是鸿蒙 6.1 arkui.componentSnapshot 组件截图坑核心!

← 返回列表