【HarmonyOS】SaveButton 保存图片
作者:zhongcx
- 2024-10-18 北京
本文字数:4851 字
阅读完需:约 16 分钟
SaveButton 组件把图片显示到相册中的方法 demo,支持组件截图、url 网络图片、base64 格式图片。
注意事项:
1、样式不支持自定义图标,试过用 opacity 修改透明度,然后添加背景来实现自定义样式,结果也失败了,opacity(1)点击生效,opacity(0.9)后点击按钮就不生效了。
2、如果带 Scroll 时,下载按钮被遮挡一部分,也无法保存到相册。
比如下面这样遮挡一点点下载按钮后,点击就没办法保存到相册了。
import photoAccessHelper from '@ohos.file.photoAccessHelper';
import fs from '@ohos.file.fs';
import { common } from '@kit.AbilityKit';
import { componentSnapshot, promptAction } from '@kit.ArkUI';
import { image } from '@kit.ImageKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { http } from '@kit.NetworkKit';
import { util } from '@kit.ArkTS';
@Entry
@Component
struct Page09 {
inviteQrCodeID: string = "inviteQrCodeID"
@State imageUrl: string =
"httpsxxxx.jpg"
@State base64Str: string =
'data:image/png;base64,iVBO........'
build() {
Scroll() {
Column({ space: 10 }) {
Column({ space: 10 }) {
Text('下载组件截图图片到相册')
Column() {
Column() {
Text('标题测试').fontSize('36lpx').height('120lpx').fontColor("#2E2E2E")
QRCode('httpswww.huxxxx.com')
.width('300lpx')
.height('300lpx')
.margin({ top: '25lpx' })
.draggable(false)
.width(140)
.height(140)
}.padding({ left: '42lpx', right: '42lpx', bottom: '20lpx' })
Text('点按下载保存至相册')
.textAlign(TextAlign.Center)
.padding({ left: '125lpx', right: '125lpx' })
.fontColor("#4B4B4B")
.fontSize('32lpx')
.margin({ bottom: '70lpx' })
}
.id(this.inviteQrCodeID)
.padding('20lpx')
.margin({ top: '30lpx', bottom: '30lpx' })
.backgroundColor(Color.White)
.borderRadius('30lpx')
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
SaveButton().onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => {
if (result === SaveButtonOnClickResult.SUCCESS) {
const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
// 免去权限申请和权限请求等环节,获得临时授权,保存对应图片
let helper = photoAccessHelper.getPhotoAccessHelper(context);
try {
// onClick触发后5秒内通过createAsset接口创建图片文件,5秒后createAsset权限收回。
let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg');
// 使用uri打开文件,可以持续写入内容,写入过程不受时间限制
let file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
componentSnapshot.get(this.inviteQrCodeID).then((pixelMap) => {
let packOpts: image.PackingOption = { format: 'image/png', quality: 100 }
const imagePacker: image.ImagePacker = image.createImagePacker();
return imagePacker.packToFile(pixelMap, file.fd, packOpts).finally(() => {
imagePacker.release(); //释放
fs.close(file.fd);
promptAction.showToast({
message: '图片已保存至相册',
duration: 2000
});
});
})
} catch (error) {
const err: BusinessError = error as BusinessError;
console.error(`Failed to save photo. Code is ${err.code}, message is ${err.message}`);
}
} else {
promptAction.showToast({
message: '设置权限失败!',
duration: 2000
});
}
})
}.borderWidth(1).borderStyle(BorderStyle.Dotted).backgroundColor(Color.Pink).padding('50lpx')
Column({ space: 10 }) {
Text('下载网络图片到相册')
/**
* 需要在 src/main/module.json5
* 添加网络权限
* {
"module": {
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
},
],
*/
Image(this.imageUrl).width('100lpx')
SaveButton().onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => {
if (result === SaveButtonOnClickResult.SUCCESS) {
const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
// 免去权限申请和权限请求等环节,获得临时授权,保存对应图片
// savePhotoToGallery(context);
let helper = photoAccessHelper.getPhotoAccessHelper(context);
try {
http.createHttp().request(
this.imageUrl,
{ expectDataType: http.HttpDataType.ARRAY_BUFFER }
).then(async (res) => {
console.info('res', JSON.stringify(res))
// 将图片资源转为像素图(PixelMap)
let pixelMap = await image.createImageSource(res.result as ArrayBuffer).createPixelMap()
// onClick触发后5秒内通过createAsset接口创建图片文件,5秒后createAsset权限收回。
let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg');
// 使用uri打开文件,可以持续写入内容,写入过程不受时间限制
let file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
let packOpts: image.PackingOption = { format: 'image/png', quality: 100 }
const imagePacker: image.ImagePacker = image.createImagePacker();
return imagePacker.packToFile(pixelMap, file.fd, packOpts).finally(() => {
imagePacker.release(); //释放
fs.close(file.fd);
promptAction.showToast({
message: '图片已保存至相册',
duration: 2000
});
});
}).catch(() => {
console.info('catch')
})
} catch (error) {
const err: BusinessError = error as BusinessError;
console.error(`Failed to save photo. Code is ${err.code}, message is ${err.message}`);
}
} else {
promptAction.showToast({
message: '设置权限失败!',
duration: 2000
});
}
})
}.borderWidth(1).borderStyle(BorderStyle.Dotted).backgroundColor(Color.Pink).padding('50lpx')
Column({ space: 10 }) {
Text('下载base64图片到相册')
Text('注意1:有些base64的格式图片显示不出来,\n是因为前缀没加data:image/png;base64,').textAlign(TextAlign.Center)
Text("注意2:下载到相册的base64字符串不能有'data:image/jpeg;base64,'这样的前缀。所以我这里用正则去掉了前缀").textAlign(TextAlign.Center)
SaveButton().onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => {
if (result === SaveButtonOnClickResult.SUCCESS) {
const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
// 免去权限申请和权限请求等环节,获得临时授权,保存对应图片
// savePhotoToGallery(context);
let helper = photoAccessHelper.getPhotoAccessHelper(context);
try {
// 正则表达式用于匹配 "data:image/*;base64," 这样的前缀
const prefixRegex = /^data:image\/[a-zA-Z]+;base64,/;
// 使用 replace 方法去除匹配到的前缀
let base64String = this.base64Str.replace(prefixRegex, '')
let buffer: ArrayBuffer =
new util.Base64Helper().decodeSync(base64String, util.Type.MIME).buffer as ArrayBuffer;
let imageSource = image.createImageSource(buffer);
let pixelMap = await imageSource.createPixelMap({ editable: true });
let opts: image.PackingOption = { format: "image/jpeg", quality: 100 };
// onClick触发后5秒内通过createAsset接口创建图片文件,5秒后createAsset权限收回。
let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg');
// 使用uri打开文件,可以持续写入内容,写入过程不受时间限制
let file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
let packOpts: image.PackingOption = { format: 'image/png', quality: 100 }
const imagePacker: image.ImagePacker = image.createImagePacker();
return imagePacker.packToFile(pixelMap, file.fd, packOpts).finally(() => {
imagePacker.release(); //释放
fs.close(file.fd);
promptAction.showToast({
message: '图片已保存至相册',
duration: 2000
});
});
} catch (error) {
const err: BusinessError = error as BusinessError;
console.error(`Failed to save photo. Code is ${err.code}, message is ${err.message}`);
}
} else {
console.info(`result:${JSON.stringify(result)}`)
promptAction.showToast({
message: '设置权限失败!',
duration: 2000
});
}
})
}
.borderWidth(1).borderStyle(BorderStyle.Dotted).backgroundColor(Color.Pink).padding('50lpx')
}.width('100%')
}.width('100%')
}
}
复制代码
划线
评论
复制
发布于: 刚刚阅读数: 4
zhongcx
关注
还未添加个人签名 2024-09-27 加入
还未添加个人简介
评论