【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()
            }
          })

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

六、总结

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

相关推荐
递归4044 天前
ofdkit-harmony 0.2.0 发布:鸿蒙原生 OFD 阅读库,已上架 ohpm
开源·harmonyos·arkts·ofd·ohpm
大雷神5 天前
HarmonyOS APP<<古今职鉴定>>开源教程第26篇:【完整案例】职业性格测试开发
harmonyos·arkts·鸿蒙·古今职鉴
大师兄666813 天前
HarmonyOS 卡片 UI 三种玩法:普通卡片、动效卡片、Canvas 卡片
harmonyos·arkts·formkit·动效卡片·canvas卡片
UnicornDev25 天前
【HarmonyOS 6】底部悬浮导航的迷你栏适配(API23)
华为·harmonyos·arkts·鸿蒙
笔触狂放1 个月前
【项目】基于ArkTS的老年人智能应用开发(1)
harmonyos·arkts·鸿蒙
UnicornDev1 个月前
【HarmonyOS 6】底部悬浮导航的沉浸光感适配(API23)
华为·harmonyos·arkts·鸿蒙·鸿蒙系统
UnicornDev1 个月前
【HarmonyOS 6】设置页面 UI 设计
ui·华为·harmonyos·arkts·鸿蒙
UnicornDev1 个月前
【HarmonyOS 6】基于API23的底部悬浮导航
华为·harmonyos·arkts·鸿蒙·鸿蒙系统
积水成渊,蛟龙生焉1 个月前
鸿蒙手势处理篇(滑动冲突、基础手势、组合手势)
华为·arkts·鸿蒙·滑动冲突·手势冲突·基础手势·组合手势
纯爱掌门人1 个月前
聊聊 HarmonyOS 上的应用内通知授权弹窗
前端·harmonyos·arkts