前言
该文章记录一下canvas绘图,后续将会逐步增加,所有内容均从网上整理而来,加上自己得理解做一个整合,方便工作中使用。
需求:微信小程序-绘制一张海报,并且保存到本地手机
代码思路
1、绘制canvas
//canvas元素要设置canvas-id,重点注意:不要再canvas元素上写type:2d
//可能uni.createCanvasContext('myCanvas')会获取不到元素
<canvas
id="myCanvas"
canvas-id="myCanvas"
:style="{
width: canvasWidth + 'px',
height: canvasHeight + 'px'
}"
></canvas>
<script setup>
import { ref } from 'vue';
const canvasWidth = 312;
const canvasHeight = 420;
const context = ref(null);
//
// 图片加载,将网络图片变成
function loadImage(src) {
return new Promise((resolve, reject) => {
uni.getImageInfo({
src: src,
success: (res) => {
resolve(res.path);
},
fail: (err) => {
reject(err);
}
});
});
}
// 绘制canvas
async function setCanvas() {
uni.showLoading({
title: '生成中...',
icon: 'none'
});
try {
context.value = uni.createCanvasContext('myCanvas');
context.value.canvasWidth = canvasWidth;
context.value.canvasHeight = canvasHeight;
// 收集所有图片加载的 Promise
const imagePromises = [
loadImage('xxx网络图片'),
loadImage('xxx网络图片'),
loadImage('xxx网络图片'),
loadImage('xxx网络图片')
];
// 等待所有图片加载完成
const images = await Promise.all(imagePromises);
// 依次绘制图片和文字
drawCanvasBgimg(images[0]);
drawMedalimg(images[1]);
drawMedalInfo(images[2], images[3]);
drawUserAvatarAndName(images[4]);
context.value.draw();
} catch (error) {
console.error('绘制出错:', error);
} finally {
uni.hideLoading();
}
}
// 绘制背景图片
function drawCanvasBgimg(imgPath) {
context.value.drawImage(imgPath, 0, 0, canvasWidth, canvasHeight);
}
// 绘制徽章图片
function drawMedalimg(imgPath) {
const x = (canvasWidth - 120) / 2;
const y = 70;
context.value.drawImage(imgPath, x, y, 120, 120);
}
// 绘制徽章 title
function drawMedalInfo(imgPath1, imgPath2) {
const allWidth = 200;
const iconWidth = 20;
const iconHeight = 20;
const x = (canvasWidth - 120) / 2;
const y = 285;
context.value.drawImage(imgPath1, x, y, iconWidth, iconHeight);
// 设置字体样式
context.value.setFontSize(18);
context.value.setFillStyle('#fde5c8');
// 绘制 title
const nameX = x + 25;
const nameY = y + 18;
context.value.fillText(info.value.title, nameX, nameY);
context.value.drawImage(imgPath2, x + 100, y, iconWidth, iconHeight);
}
// 绘制用户头像和昵称
function drawUserAvatarAndName(imgPath) {
const avatarWidth = 35;
const avatarHeight = 35;
const avatarX = 20;
const avatarY = canvasHeight - avatarHeight - 20;
context.value.save();
const radius = avatarWidth / 2;
const centerX = avatarX + radius;
const centerY = avatarY + radius;
context.value.beginPath();
context.value.arc(centerX, centerY, radius, 0, 2 * Math.PI);
context.value.closePath();
context.value.clip();
context.value.drawImage(
imgPath,
avatarX,
avatarY,
avatarWidth,
avatarHeight
);
context.value.restore();
// 设置字体样式
context.value.setFontSize(16);
context.value.setFillStyle('#fff');
// 绘制昵称,位置在头像右侧
const nameX = avatarX + avatarWidth + 10;
const nameY = avatarY + avatarHeight / 2 + 5;
context.value.fillText(userInfo.value.nickname, nameX, nameY);
}
</script>
2、保存到手机
//保持到手机-首先要检查微信授权问题
//
const saveImage = async () => {
try {
uni.showLoading();
// 获取用户设置
const { authSetting } = await uni.getSetting();
// 没有权限的时候
if (!authSetting['scope.writePhotosAlbum']) {
await getAuthorize('scope.writePhotosAlbum', {
title: '请授权保存到相册',
callback: addIamgeToAlbum
});
return;
}
await addIamgeToAlbum();
} catch (err) {
} finally {
uni.hideLoading();
}
};
//保存canvas图片到本机函数
const addIamgeToAlbum = async () => {
try {
const { tempFilePath } = await uni.canvasToTempFilePath({
canvasId: 'myCanvas',
destWidth: canvasWidth,
destHeight: canvasHeight,
quality: 1
});
await uni.saveImageToPhotosAlbum({
filePath: tempFilePath
});
uni.showToast({
title: '保存成功!'
});
} catch {}
};