uniapp 编译支付宝小程序canvas 合成图片实例,支付宝小程序 canvas 渲染图片 可以换成自己的图片即可

文章目录

  • 前言
  • [一、在页面中使用 Canvas](#一、在页面中使用 Canvas)
  • [二、在页面的 JS 文件中绘制图片](#二、在页面的 JS 文件中绘制图片)
  • 总结

前言

uniapp 编译支付宝小程序canvas 合成图片实例,支付宝小程序 canvas 渲染图片 可以换成自己的图片即可


一、在页面中使用 Canvas

html 复制代码
<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 上下文,并绘制图片。

javascript 复制代码
<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 方法获取图片信息,例如尺寸等,然后再进行绘制。

相关推荐
從南走到北6 小时前
JAVA代泊车接机送机服务代客泊车系统源码支持小程序+APP+H5
java·开发语言·微信小程序·小程序
软件技术员13 小时前
微信小程序电子测宅堪墓风水罗盘
微信小程序·小程序
future_studio14 小时前
聊聊 Unity(小白专享、C# 小程序 之 播放器)
unity·小程序·c#
Q_Q51100828514 小时前
python+uniapp基于微信小程序的旅游信息系统
spring boot·python·微信小程序·django·flask·uni-app·node.js
小Tomkk14 小时前
Rokid 开发空间小程序 实战
3d·小程序·rokid·jsar
说私域15 小时前
基于多模态AI技术的传统行业智能化升级路径研究——以开源AI大模型、AI智能名片与S2B2C商城小程序为例
人工智能·小程序·开源
2501_9160074716 小时前
iOS 混淆工具链实战,多工具组合完成 IPA 混淆与加固(iOS混淆|IPA加固|无源码混淆|App 防反编译)
android·ios·小程序·https·uni-app·iphone·webview
游戏开发爱好者818 小时前
FTP 抓包分析实战,命令、被动主动模式要点、FTPS 与 SFTP 区别及真机取证流程
运维·服务器·网络·ios·小程序·uni-app·iphone
说私域18 小时前
基于开源AI大模型、AI智能名片与S2B2C商城小程序的购物中心精准零售数据架构研究
人工智能·小程序·开源