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

相关推荐
咖啡の猫18 分钟前
小程序协同工作和发布
小程序
维双云1 小时前
小程序怎么制作工具?与其盲目找开发,不如先分清自己要哪一种
小程序
qq_9109462921 小时前
校园共享电动车租赁小程序
小程序
侃谈科技圈1 小时前
5G网络仿真软件哪个更高效?Ranplan两款核心产品深度解析
小程序
m0_474606781 小时前
JAVA - 使用Apache POI 自定义报表字段手写导出(支持-合并单元格)
java·开发语言·apache
Harm灬小海2 小时前
【云计算学习之路】企业常用服务搭建:构建Apache WEB服务器
运维·服务器·学习·云计算·apache
小羊Yveesss2 小时前
微信小程序年度费用全拆解:SaaS、开源与定制开发的3年成本实测对比
微信小程序·小程序·开源
2501_9160074718 小时前
iOS开发中抓取HTTPS请求的完整解决方法与步骤详解
android·网络协议·ios·小程序·https·uni-app·iphone
jay神19 小时前
基于微信小程序课外创新实践学分认定系统
java·spring boot·小程序·vue·毕业设计
顧棟1 天前
Apache-doris 集群扩缩容迁移方案
apache