uniapp 编译支付宝小程序canvas 合成图片实例,支付宝小程序 canvas 渲染图片 可以换成自己的图片即可
文章目录
- 前言
- 一、在页面中使用 Canvas
- 二、在页面的 JS 文件中绘制图片
- 总结
前言
uniapp 编译支付宝小程序canvas 合成图片实例,支付宝小程序 canvas 渲染图片 可以换成自己的图片即可
一、在页面中使用 Canvas
<template><view><!-- Canvas 画布 --><canvas type="2d" :id="alipayCanvasId":style="canvasStyle":width="canvasWidth" :height="canvasHeight"@ready="onCanvasReady" /><!-- 生成的海报预览 --><image v-if="finalPosterUrl" :src="finalPosterUrl" mode="widthFix" style="width: 100%; margin-top: 20rpx"show-menu-by-longpress="true"/></view>
</template>
二、在页面的 JS 文件中绘制图片
你可以使用 myCanvas 这个 canvas-id 来获取 canvas 上下文,并绘制图片。
<script>
export default {data() {return {finalPosterUrl: '', // 生成的海报临时路径alipayCanvasId:"alipayPosterCanvas",alipayCanvas: null, // Canvas 实例alipayCtx: null, // 2D 上下文dpr: 1, // 设备像素比// Canvas 基础配置canvasWidth: 0, // 动态计算的canvas宽度canvasHeight: 0, // 动态计算的canvas高度canvasStyle: "", // canvas样式};},methods: {/*** Canvas 就绪回调*/onCanvasReady() {// 图片资源const mainImgUrl = 'xxxxxx/haibao_image.png';const qrImgUrl = 'xxxxxx/0379ec3faccad8485f136bd94b1486e1e367ac8c.jpeg';// 查询 Canvas 节点uni.createSelectorQuery()// 绑定当前组件上下文(关键).select(`#${this.alipayCanvasId}`).node().exec(async (res) => {if (!res || !res[0] || !res[0].node) {console.error('未找到 Canvas 节点');return;}// 初始化 Canvas 环境this.initCanvasEnv(res[0].node);try {// 分步加载并绘制图片(使用封装的方法)const mainImg = await this.loadImage(mainImgUrl);this.drawMainImage(mainImg);const qrImg = await this.loadImage(qrImgUrl);this.drawQrCode(qrImg);// 转换为临时图片this.convertToTempImage();} catch (err) {console.error('海报生成失败:', err);uni.showToast({ title: '生成失败', icon: 'none' });}});},/*** 初始化 Canvas 环境(尺寸、上下文等)*/initCanvasEnv(canvasNode) {this.alipayCanvas = canvasNode;this.alipayCtx = canvasNode.getContext('2d');// 获取设备信息const sysInfo = uni.getSystemInfoSync();this.dpr = sysInfo.pixelRatio || 1;// 计算逻辑宽高(750rpx = 屏幕宽度)this.canvasWidth = sysInfo.screenWidth;this.canvasHeight = (1200 / 750) * sysInfo.screenWidth;// 设置实际像素尺寸(解决模糊问题)this.alipayCanvas.width = this.canvasWidth * this.dpr;this.alipayCanvas.height = this.canvasHeight * this.dpr;// 缩放上下文this.alipayCtx.scale(this.dpr, this.dpr);},/*** 封装:加载图片(支持网络图片下载 + Canvas 图片对象转换)* @param {String} url - 图片URL* @returns {Promise} - 加载完成的图片对象*/loadImage(url) {return new Promise(async (resolve, reject) => {try {// 1. 下载网络图片(支付宝需要先下载为本地临时路径)const tempPath = await this.downloadImage(url);// 2. 将临时路径转换为 Canvas 可绘制的图片对象const img = this.alipayCanvas.createImage();img.onload = () => resolve(img);img.onerror = () => reject(new Error(`图片加载失败: ${url}`));img.src = tempPath; // 使用下载后的临时路径} catch (err) {reject(err);}});},/*** 封装:下载网络图片为本地临时路径* @param {String} url - 图片URL* @returns {Promise} - 本地临时路径*/downloadImage(url) {return new Promise((resolve, reject) => {// 校验URL有效性if (!url || typeof url !== 'string') {reject(new Error(`无效的图片URL: ${url}`));return;}uni.downloadFile({url,success: (res) => {if (res.statusCode === 200) {resolve(res.tempFilePath); // 返回临时路径} else {reject(new Error(`下载失败,状态码: ${res.statusCode}`));}},fail: (err) => {reject(new Error(`下载错误: ${err.errMsg}`));}});});},/*** 绘制主图* @param {Object} img - 主图图片对象*/drawMainImage(img) {// 铺满整个画布this.alipayCtx.drawImage(img, 0, 0, this.canvasWidth, this.canvasHeight);},/*** 绘制二维码* @param {Object} img - 二维码图片对象*/drawQrCode(img) {// 二维码尺寸(画布宽度的30%)const qrSize = this.canvasWidth * 0.3;// 二维码位置(底部居中,距离底部20rpx)const qrX = (this.canvasWidth - qrSize) / 2;const qrY = this.canvasHeight - qrSize - (20 / 750) * this.canvasWidth;// 绘制白色背景(增强对比度)this.alipayCtx.fillStyle = '#ffffff';this.alipayCtx.fillRect(qrX - 10, qrY - 10, qrSize + 20, qrSize + 20);// 绘制二维码this.alipayCtx.drawImage(img, qrX, qrY, qrSize, qrSize);},/*** 转换 Canvas 为临时图片*/convertToTempImage() {uni.canvasToTempFilePath({canvasId: this.alipayCanvasId,width: this.canvasWidth,height: this.canvasHeight,destWidth: this.canvasWidth * this.dpr, // 输出高清图destHeight: this.canvasHeight * this.dpr,success: (res) => {this.finalPosterUrl = res.tempFilePath;console.log('海报生成成功:', res.tempFilePath);},fail: (err) => {console.error('转换图片失败:', err);uni.showToast({ title: '转换失败', icon: 'none' });}}, this);}}
};
</script>
总结
注意事项
跨域问题:如果图片 URL 是外部链接,确保服务器支持跨域请求,或者在支付宝小程序管理后台添加图片的域名到“业务域名”白名单中。
图片加载:由于网络请求和图片加载可能需要时间,建议在 onReady 或在图片加载成功后调用 drawImage 方法。
动态图片:如果图片是动态生成的或者来自用户上传,确保在调用 drawImage 前图片已经加载完成。可以使用 my.getImageInfo 方法获取图片信息,例如尺寸等,然后再进行绘制。