uni-app vue3创建 canvas 画布,保存到相册报错
uni-app vue3创建 canvas 画布,保存到相册报错
测试过的手机:
mate60
示例代码:
<template>
<view>
<canvas style="width: 300px; height: 400px;"
canvas-id="firstCanvas" id="firstCanvas"></canvas>
<button @click="saveImage11">保存</button>
</view>
</template>
<script>
export default {
data() {
return {
selectId: 'firstCanvas',
scrollLeft: 0,
canvas: null
}
},
props: ['content'],
watch: {
content(value) {
if (value) {
this.createCanvas11()
}
}
},
methods: {
// 生成canvas
createCanvas11() {
const ctx = uni.createCanvasContext('firstCanvas', this);
ctx.clearRect(0, 0, 300, 400)
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(0, 0, 300, 400);
function findBreakPoint(text, width, context) {
var min = 0;
var max = text.length - 1;
while (min <= max) {
var middle = Math.floor((min + max) / 2);
var middleWidth = context.measureText(text.substr(0, middle)).width;
var oneCharWiderThanMiddleWidth = context.measureText(text.substr(0, middle + 1)).width;
if (middleWidth <= width && oneCharWiderThanMiddleWidth > width) {
return middle;
}
if (middleWidth < width) {
min = middle + 1;
} else {
max = middle - 1;
}
}
return -1;
}
function breakLinesForCanvas(text, width, font) {
var result = [];
var breakPoint = 0;
if (font) {
ctx.font = font;
}
while ((breakPoint = findBreakPoint(text, width, ctx)) !== -1) {
result.push(text.substr(0, breakPoint));
text = text.substr(breakPoint);
}
if (text) {
result.push(text);
}
return result;
}
ctx.strokeRect(5, 5, 292, 392)
ctx.setFillStyle('black')
const content = breakLinesForCanvas(this.content, 260, '28px 微软雅黑');
content.forEach(function(line, index) {
ctx.fillText(line, 20, 30 * index + 50);
});
ctx.drawImage("/static/er.jpg", 20, 260, 100, 100);
let wordsList = [
'长按识别二维码',
'一天一句毒鸡汤',
'每天一碗,人生耀眼'
]
ctx.setFontSize(14)
ctx.fillText(wordsList[0], 25, 380);
ctx.setFontSize(18)
ctx.fillText(wordsList[1], 140, 310);
ctx.setFontSize(16)
ctx.fillText(wordsList[2], 130, 340);
this.canvas = ctx
ctx.draw()
},
// 保存到相册
saveImage11() {
let that = this;
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: 300,
height: 400,
destWidth: 900,
destHeight: 1200,
// fileType: 'jpg',
// quality: 1,
canvasId: 'firstCanvas',
canvas: this.canvas,
success: function(res) {
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success() {
that.canvasFlag = false
that.$refs.shareBox.close();
uni.showToast({
title: '保存成功!',
duration: 2000
});
}
})
},
fail: function ( res ) {
console.log(res)
}
})
}
}
}
</script>
操作步骤:
这段代码用的是 vue2 语法,运行环境为 vue3,canvas 能正常加载,但是保存 canvas 到临时目录报错。
预期结果:
正常保存
实际结果:
报错
1 回复
在使用 uni-app 和 Vue 3 创建 canvas 画布并保存到相册时,可能会遇到一些常见问题。以下是一些可能的原因和解决方案:
1. Canvas 绘制内容未完成
- 问题: 在保存 canvas 内容之前,可能 canvas 的绘制还没有完成。
- 解决方案: 确保在保存之前,canvas 的绘制已经完成。可以使用
setTimeout
或者Promise
来确保绘制完成后再进行保存。
// 假设 canvasId 是你的 canvas 组件的 id
const canvas = uni.createCanvasContext('canvasId');
canvas.draw(); // 绘制内容
canvas.draw(false, () => {
// 绘制完成后保存
uni.canvasToTempFilePath({
canvasId: 'canvasId',
success: (res) => {
const tempFilePath = res.tempFilePath;
uni.saveImageToPhotosAlbum({
filePath: tempFilePath,
success: () => {
console.log('保存成功');
},
fail: (err) => {
console.error('保存失败', err);
}
});
},
fail: (err) => {
console.error('生成临时文件失败', err);
}
});
});
2. 权限问题
- 问题: 保存到相册需要用户授权,如果没有授权,保存操作会失败。
- 解决方案: 在保存之前,先检查并请求相册权限。
uni.getSetting({
success(res) {
if (!res.authSetting['scope.writePhotosAlbum']) {
uni.authorize({
scope: 'scope.writePhotosAlbum',
success() {
// 用户授权成功,继续保存操作
},
fail() {
console.error('用户拒绝授权');
}
});
} else {
// 已有权限,继续保存操作
}
}
});
3. Canvas 尺寸问题
- 问题: 如果 canvas 的尺寸过大或过小,可能会导致保存失败。
- 解决方案: 确保 canvas 的尺寸合理,并且在保存时指定正确的宽度和高度。
uni.canvasToTempFilePath({
canvasId: 'canvasId',
width: 300, // 指定宽度
height: 300, // 指定高度
success: (res) => {
const tempFilePath = res.tempFilePath;
uni.saveImageToPhotosAlbum({
filePath: tempFilePath,
success: () => {
console.log('保存成功');
},
fail: (err) => {
console.error('保存失败', err);
}
});
},
fail: (err) => {
console.error('生成临时文件失败', err);
}
});