本文是「鸿蒙 6.1 API 23 开发坑系列」第 2 篇(ArkUI 桶第 2 篇)。本篇讲 @ohos.arkui.componentSnapshot namespace(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.componentSnapshot namespace(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

componentSnapshot 初始态 get(id) 异步截图态 getSync(id) 同步截图态 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);SysCap SystemCapability.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): void callback 异步(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.componentSnapshot namespace(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.componentSnapshot namespace(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 组件截图坑核心!

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐