HarmonyOS鸿蒙Next中如何将Canvas绘制的资源以图片的形式保存至图库
HarmonyOS鸿蒙Next中如何将Canvas绘制的资源以图片的形式保存至图库 1、自定义绘制的Canvas如何转为图片?
2、图片保存方案种类繁杂,申请各种权限成为您前进路上的绊脚石?
无需申请任何权限,即可完成。
实现步骤:
- 将Canvas组件赋予一个id,通过组件id截图的形式获取到对应的pixelMap;
- 通过SaveButton安全控件将pixelMap通过imagePackerApi.packToFile()这个API直接编写进文件即可。
- ImagePacker:图片编码器类,用于图片压缩和编码。在调用ImagePacker的方法前,需要先通过createImagePacker构建一个ImagePacker实例。
- SaveButton:安全控件的保存控件。应用集成保存控件后,用户首次使用保存控件展示弹窗,在点击允许后自动授权,应用会在短时间内获取访问媒体库特权接口的授权。后续使用无需弹窗授权。在API version 19及之前的版本中,授权持续时间为10秒;在API version20及之后的版本中,授权持续时间为1分钟。
真机效果:

关键代码:
1、id截图的形式获取到对应的pixelMap
@Local pixelMap?: image.PixelMap
private cvsID: string = 'canvasId'
//...
this.getUIContext().getComponentSnapshot().get(this.cvsID, (error: Error, pixmap: image.PixelMap) => {
})
2、imagePackerApi.packToFile()将pixelMap编写进图库
imagePackerApi.packToFile(this.pixelMap, file.fd, packOpts, (err: BusinessError) => {
if (err) {
} else {
imagePackerApi.release((err: BusinessError) => {
if (err) {
} else {
fileIo.close(file.fd);
}
})
promptAction.showToast({ message: '已保存至相册!' });
}
})
完整代码:
import { image } from "@kit.ImageKit";
import { common } from "@kit.AbilityKit";
import { photoAccessHelper } from "@kit.MediaLibraryKit";
import { fileIo } from "@kit.CoreFileKit";
import { promptAction } from "@kit.ArkUI";
import { BusinessError } from '@kit.BasicServicesKit';
@ComponentV2
export struct CanvasSaveImg {
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private ctx: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
@Local pixelMap?: image.PixelMap
private cvsID: string = 'canvasId'
private context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
build() {
Scroll() {
Column() {
Canvas(this.ctx)
.width(200)
.height(200)
.backgroundColor('#F5DC62')
.onReady(() => {
// 设定填充样式,填充颜色设为蓝色
this.ctx.fillStyle = '#ff7f27'
// 以(50, 50)为左上顶点,画一个宽高400的矩形B
this.ctx.fillRect(10, 10, 190, 190)
this.ctx.fillStyle = '#22b14c';
// 以(50, 50)为左上顶点,画一个宽高200的矩形A
this.ctx.fillRect(10, 10, 80, 80);
})
.id(this.cvsID)
Blank().height(30)
SaveButton({ text: SaveDescription.SAVE_IMAGE }).width('80%')
.onClick((event: ClickEvent, result: SaveButtonOnClickResult) => {
if (result === SaveButtonOnClickResult.SUCCESS) {
// 免去权限申请和权限请求等环节,获得临时授权,保存对应图片。
this.getUIContext().getComponentSnapshot().get(this.cvsID, (error: Error, pixmap: image.PixelMap) => {
this.pixelMap = pixmap;
this.savePixelMap();
});
} else {
promptAction.openToast({ message: '设置权限失败!' });
}
})
}.safeAreaPadding({ top: 30 })
.width('100%')
.height('100%')
}
.width('100%')
.height('100%')
}
async savePixelMap() {
// 获取相册的保存路径
let helper = photoAccessHelper.getPhotoAccessHelper(this.context);
let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpeg');
let file = await fileIo.open(uri, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
let imagePackerApi = image.createImagePacker();
let packOpts: image.PackingOption = { format: 'image/jpeg', quality: 98 };
imagePackerApi.packToFile(this.pixelMap, file.fd, packOpts, (err: BusinessError) => {
if (err) {
console.error(`Failed to pack the image to file.code ${err.code},message is ${err.message}`);
} else {
console.info('Succeeded in packing the image to file.');
imagePackerApi.release((err: BusinessError) => {
if (err) {
console.error(`Failed to release the image source instance.code ${err.code},message is ${err.message}`);
} else {
console.info('Succeeded in releasing the image source instance.');
fileIo.close(file.fd);
}
})
promptAction.showToast({ message: '已保存至相册!' });
}
})
}
}
组件引用
@Entry
@ComponentV2
struct Index {
build() {
Column() {
CanvasSaveImg()
}
.height('100%')
.width('100%')
}
}
相关文档:
更多关于HarmonyOS鸿蒙Next中如何将Canvas绘制的资源以图片的形式保存至图库的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中,使用Canvas绘制内容后,可通过PixelMap和ImagePacker将绘制结果转换为图片数据。使用@ohos.file.fs和@ohos.file.photoAccessHelper模块,将图片数据写入应用沙箱路径,再通过PhotoAccessHelper接口将文件插入系统图库,实现保存。
在HarmonyOS Next中,将Canvas绘制内容保存为图片并存入图库,核心流程分为两步:Canvas转图片与图片写入媒体库。下面提供基于ArkTS的简洁实现方案。
1. Canvas转图片
使用Canvas组件的toDataURL方法,可将当前绘制内容转换为Base64格式的图片数据。
import { drawing } from '@kit.ArkGraphics2D';
// 假设您的Canvas组件已通过ref绑定
@State canvasRef: CanvasRenderingContext2D | null = null;
// 在绘制完成后调用
const convertCanvasToImage = (): string => {
if (!this.canvasRef) {
return '';
}
// 生成Base64格式的图片数据(默认为PNG)
const dataURL = this.canvasRef.toDataURL();
return dataURL; // 格式为:"data:image/png;base64,iVBORw0KGgo..."
}
2. 保存图片至图库
需使用媒体库管理模块(@kit.MediaLibraryKit)将图片数据写入公共目录。关键步骤包括:
a. 申请必要权限
在module.json5中声明以下权限:
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.READ_IMAGEVIDEO",
"reason": "$string:reason_desc" // 填写您的描述
},
{
"name": "ohos.permission.WRITE_IMAGEVIDEO",
"reason": "$string:reason_desc"
}
]
}
}
注意:HarmonyOS Next的权限模型需同步在应用配置中明确声明,并在运行时通过abilityAccessCtrl发起动态授权请求。
b. 写入媒体库
import { mediaLibrary } from '@kit.MediaLibraryKit';
import { fileIo } from '@kit.CoreFileKit';
async saveImageToGallery(base64Data: string) {
// 1. 获取媒体库实例
const media = mediaLibrary.getMediaLibrary();
// 2. 创建公共图片目录(如果不存在)
const publicDir = await media.getPublicDirectory(mediaLibrary.DirectoryType.DIR_IMAGE);
// 3. 生成唯一文件名
const fileName = `canvas_${Date.now()}.png`;
const filePath = `${publicDir}/${fileName}`;
// 4. 解码Base64并写入文件
const buffer = this.base64ToArrayBuffer(base64Data.split(',')[1]); // 去除DataURL前缀
await fileIo.writeFile(filePath, buffer);
// 5. 通知媒体库扫描新文件(可选,使图片立即在图库中可见)
await mediaLibrary.scanFile(filePath);
}
// Base64转ArrayBuffer工具方法
private base64ToArrayBuffer(base64: string): ArrayBuffer {
const binaryString = atob(base64);
const len = binaryString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes.buffer;
}
完整调用示例
// 在保存按钮事件中整合流程
async onSaveButtonClick() {
// 转换Canvas
const imageData = this.convertCanvasToImage();
if (!imageData) {
return;
}
// 保存至图库
await this.saveImageToGallery(imageData);
}
关键说明
- 权限申请:HarmonyOS Next要求显式声明并动态申请媒体读写权限,这是写入公共图库的必要条件。
- 文件路径:必须使用
getPublicDirectory获取公共目录,私有目录文件无法被图库应用访问。 - 性能考虑:大尺寸Canvas转换时,建议在异步任务中处理编码与写入操作,避免阻塞UI。
此方案直接使用HarmonyOS Next标准API,避免了依赖第三方库的复杂度。实际开发中需根据您的Canvas实现上下文调整引用获取方式。

