【HarmonyOS ArkTS】获取组件截图并保存到相册

写在前面

本文基于项目中的文件,详细说明组件截图及保存到相册的实现逻辑。 适合 HarmonyOS 开发初学者理解如何在 ArkTS 中完成组件截图、图片保存至缓存路径与图片保存至相册的操作。

一、整体流程

  1. 对特定组件截图
  2. 将图片压缩并写入到缓存目录
  3. 将图片保存到本地相册

二、代码实现

typescript 复制代码
// 模块导入
import { componentSnapshot, promptAction } from "@kit.ArkUI"
import { image } from "@kit.ImageKit"
import { fileIo, fileUri } from "@kit.CoreFileKit"
import { photoAccessHelper } from "@kit.MediaLibraryKit"

async saveImg() {
  // 1. 对特定组件截图
  const pixelMap = await componentSnapshot.get('share')
  
  // 2. 将图片压缩并写入到缓存目录
  const packer = image.createImagePacker()
  const arrayBuffer = await packer.packToData(pixelMap, { format: 'image/jpeg', quality: 70 })
  const cxt = getContext()
  const imgPath = cxt.cacheDir + '/' + Date.now() + '.jpeg'
  const imgFile =
    fileIo.openSync(imgPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE)
  fileIo.closeSync(imgFile)
  
  // 3. 将图片保存到本地相册
  const imgUri = fileUri.getUriFromPath(imgPath)
  const request = photoAccessHelper.MediaAssetChangeRequest.createImageAssetRequest(cxt, imgUri)
  const helper = photoAccessHelper.getPhotoAccessHelper(cxt)
  await helper.applyChanges(request)

  promptAction.showToast({ message: '图片已保存到本地' })
}

三、结构说明

1. 对特定组件截图

typescript 复制代码
import { componentSnapshot } from "@kit.ArkUI"

@Component
struct PreviewComponent {
  @State id: string = 'share';

  build() {
    Column() {
      // 需要截图的组件
      Image($r('app.media.banner'))
        .id(this.id)
        
      Button('保存截图')
        .onClick(() => this.saveImg())
    }
  }

 async saveImg() {
   // 1. 对特定组件截图
   const pixelMap = await componentSnapshot.get('share')

  //......
 }
}

说明:

  • 将需要截图的组件的id填入componentSnapshot.get的参数中
  • 结果为pixelMap格式的图片数据

2. 将图片压缩并写入到缓存目录

typescript 复制代码
import { image } from "@kit.ImageKit"
import { fileIo } from "@kit.CoreFileKit"


async saveImg() {
  //......
  
  // 2. 将图片压缩并写入到缓存目录
  // image.createImagePacker()函数的返回值是ImagePacker对象
  const packer = image.createImagePacker()
  // 将图片压缩或重新编码,返回的结果为二进制数据流
  const arrayBuffer = await packer.packToData(pixelMap, { format: 'image/jpeg', quality: 70 }) // 图片质量(1-100)

  // 获取缓存路径
  const cxt = getContext()
  const imgPath = cxt.cacheDir + '/' + Date.now() + '.jpeg'

  // 创建临时文件对象,给fileIo创建和写入权限,写入压缩后的图片数据
  const imgFile =
    fileIo.openSync(imgPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE)
  // 将图片写入到缓存路径
  fileIo.writeSync(imgFile.fd, arrayBuffer)
  // 关闭后file对象不再具备实际意义 不可再用于进行读写等操作
  fileIo.closeSync(imgFile)

  //......
}

说明:

  • 使用 ImagePacker 对pixelMap格式数据进行压缩并打包
  • 使用 fileIo 模块将图片写入到缓存目录
  • 操作完后注意关闭file对象

3. 将图片保存到本地相册

typescript 复制代码
import { promptAction } from "@kit.ArkUI"
import { fileUri } from "@kit.CoreFileKit"
import { photoAccessHelper } from "@kit.MediaLibraryKit"

async saveImg() {
  //......
  
  // 3. 将图片保存到本地相册
  // 获取图片的完整路径( getContext获取的是部分路径 )
  const imgUri = fileUri.getUriFromPath(imgPath)
  // 创建一个 向相册发送修改数据 的请求
  const request = photoAccessHelper.MediaAssetChangeRequest.createImageAssetRequest(cxt, imgUri)

  // 获取照片访问助手实例,用于接收请求
  const helper = photoAccessHelper.getPhotoAccessHelper(cxt)

  // 调用助手实例上的方法, 将图片保存到本地 ( 需要相册的相关权限 )
  await helper.applyChanges(request)

  promptAction.showToast({ message: '图片已保存到本地' })
}

说明:

  • 使用 fileUri 获取图片的完整路径
  • 通过 photoAccessHelper 模块得到修改请求和图片访问助手
  • 将图片保存到本地 ( 需要相册的相关权限 )

四、相关模块说明

模块 功能
componentSnapshot 对已渲染的组件进行截图
promptAction 创建并显示文本提示框
image 提供图片的解码和编码能力
fileIo 提供文件存储管理能力
fileUri 通过PATH获取文件统一资源标志符
photoAccessHelper 提供相册管理能力

五、补充

如果没有向用户申请相册的相关权限,我们也可以用华为内置的安全控件完成保存功能,此时用户通过点击该保存按钮,可以临时获取存储权限,而不需要权限弹框授权确认。

typescript 复制代码
// 
 SaveButton({
          text: SaveDescription.SAVE_IMAGE,
          buttonType: ButtonType.Normal,
          icon: SaveIconStyle.FULL_FILLED
        })
          .onClick((event, result) => {
            if (result == SaveButtonOnClickResult.SUCCESS) {
              this.saveImg()
              // 自己关自己
              this.controller.close()
            }
          })

为了保障用户的隐私不被恶意应用获取,华为针对安全控件作了很多的限制,比如其对象参数内属性的值都是枚举,开发者并不能对其样式做过多更改。

六、总结

本文提供了一个获取组件截图并保存到相册的主要流程,并提供了一个临时获取相册存储权限的方式,希望能帮助开发者快速掌握保存图片的核心代码实现。

相关推荐
UnicornDev4 分钟前
【HarmonyOS 6】底部悬浮导航的迷你栏适配(API23)
华为·harmonyos·arkts·鸿蒙
笔触狂放19 小时前
【项目】基于ArkTS的老年人智能应用开发(1)
harmonyos·arkts·鸿蒙
UnicornDev2 天前
【HarmonyOS 6】底部悬浮导航的沉浸光感适配(API23)
华为·harmonyos·arkts·鸿蒙·鸿蒙系统
UnicornDev7 天前
【HarmonyOS 6】设置页面 UI 设计
ui·华为·harmonyos·arkts·鸿蒙
UnicornDev10 天前
【HarmonyOS 6】基于API23的底部悬浮导航
华为·harmonyos·arkts·鸿蒙·鸿蒙系统
积水成渊,蛟龙生焉10 天前
鸿蒙手势处理篇(滑动冲突、基础手势、组合手势)
华为·arkts·鸿蒙·滑动冲突·手势冲突·基础手势·组合手势
纯爱掌门人11 天前
聊聊 HarmonyOS 上的应用内通知授权弹窗
前端·harmonyos·arkts
UnicornDev13 天前
【HarmonyOS 6】练习记录页面 UI 设计
ui·华为·harmonyos·arkts·鸿蒙
哈__14 天前
新手入门harmonyOS开发:手把手教你用ArkTS实现一个天气应用
harmonyos·arkts
积水成渊,蛟龙生焉14 天前
鸿蒙装饰器V2详解
华为·harmonyos·arkts·鸿蒙·ark