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 小时前
【开题答辩全过程】以 基于微信小程序的农商新闻网为例,包含答辩的问题和答案
微信小程序·小程序
小光学长6 小时前
基于微信小程序的家具商城系统g80l9675(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·微信小程序·小程序
云起SAAS6 小时前
1V1七彩测评抖音快手微信小程序看广告流量主开源
微信小程序·小程序·ai编程·看广告变现轻·1v1七彩测评
sheji34166 小时前
【开题答辩全过程】以 基于微信小程序的签到系统的设计与实现为例,包含答辩的问题和答案
微信小程序·小程序
脾气有点小暴6 小时前
uniapp滚动容器冲突
uni-app
鱼樱前端8 小时前
uni-app开发app之前提须知(IOS/安卓)
前端·uni-app
说私域8 小时前
基于开源链动2+1模式AI智能名片S2B2C商城小程序的社群运营创新研究
人工智能·小程序·开源
chinrock8 小时前
如何抓包飞书小程序-飞书开发者工具
小程序·飞书
wasp5201 天前
Apache Hudi 项目总体分析
数据挖掘·apache·hudi·数据湖仓
二狗mao1 天前
Uniapp使用websocket进行ai回答的流式输出
websocket·网络协议·uni-app