uniapp-canvas绘图

178 阅读2分钟

前言

该文章记录一下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 {}
};