微信小程序canvas绘制携带二维码的海报图下载,解决canvas中的文字不会换行问题

需求:

将背景图片和生成的二维码图片合并成一张图片,可以让用户下载该图片

效果:

在这里插入图片描述

话不多说直接上代码

  1. 首先需要再页面定义一个canvas容器
<button bindtap="generatePosters">点击生成海报</button>

<block wx:if="{{isFlag}}">
  <canvas type="2d" id="myCanvas" class="myCanvas"></canvas>
  <!-- 下载图片按钮 -->
  <button bindtap="addImage" class="add_btn">下载图片</button>
</block>
  1. 然后就是js部分
Page({
  data: {
    imageUrl: 'https://img2.baidu.com/it/u=1884974821,3634354042&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=679',
    title: '扫描二维码,加入我们,新人优惠,特价商品',
    code: '/static/1686968496385.jpg',
    isFlag: false
  },
  generatePosters() {
    this.setData({
      isFlag: !this.data.isFlag
    })
    const query = wx.createSelectorQuery()
    query.select('#myCanvas')
      .fields({
        node: true,
        size: true
      })
      .exec((res) => {
        const canvas = res[0].node
        const ctx = canvas.getContext('2d')
        // 获取像素比
        const dpr = wx.getSystemInfoSync().pixelRatio
        // 将画布大小按照设备像素比例进行调整,使其在不同设备上显示的效果更加一致。
        canvas.width = res[0].width * dpr
        canvas.height = res[0].height * dpr
        ctx.scale(dpr, dpr)
        // 设置背景图片
        const bg = canvas.createImage()
        bg.src = this.data.imageUrl
        bg.onload = () => {
          ctx.drawImage(bg, 0, 0, 300, 400)
        }
        // 绘制 底部 盒子
        ctx.fillStyle = '#f0f0f0'
        ctx.fillRect(0, 400, 500, 100)
        ctx.fill()
        // 设置 字体
        ctx.fillStyle = '#000'
        ctx.font = "16px 楷体"
        ctx.fillText(this.data.title, 12, 450)
        ctx.fill()
        // 生成 二维码
        const code = canvas.createImage()
        code.src = this.data.code
        code.onload = () => {
          ctx.drawImage(code, 220, 420, 60, 60)
        }
        this.setData({
          canvas: canvas
        })
      })
  },
})
  1. 做好这些后我们会发现在canvas中绘制的文字是不会换行的,需要我们自己去写,具体该函数怎么用看最后总代码
 /**
   *  参数解析:
   * 	ctx:  canvas绘图上下文
   * 	str:  需要绘制的文本内容
   * 	draw_width:  绘制后的文字显示宽度
   * 	lineNum:  最大行数,多出部分用'...'表示, 如果传-1可以达到自动换行效果
   * 	startX:  绘制文字的起点 X 轴坐标
   * 	startY:  绘制文字的起点 Y 轴坐标
   *	steps:  文字行间距
   */
  toFormateStr(ctx, str, draw_width, lineNum, startX, startY, steps) {
    let strWidth = ctx.measureText(str).width; // 测量文本源尺寸信息(宽度)
    let startpoint = startY,
      keyStr = '',
      sreLN = strWidth / draw_width; // 文本长度除以换行的宽 得到一共生成多少行
    let liner = Math.ceil(sreLN); // 计算文本源一共能生成多少行
    let strlen = parseInt(str.length / sreLN); // 等比缩放测量一行文本显示多少个字符
    // 若文本不足一行,则直接绘制,反之大于传入的最多行数(lineNum)以省略号(...)代替
    if (strWidth < draw_width) {
      ctx.fillText(str, startX, startpoint);
    } else {
      for (let i = 1; i < liner + 1; i++) {
        let startPoint = strlen * (i - 1);
        if (i < lineNum || lineNum == -1) {
          keyStr = str.substr(startPoint, strlen);
          ctx.fillText(keyStr, startX, startpoint);
        } else {
          keyStr = str.substr(startPoint, strlen - 5) + '...';
          ctx.fillText(keyStr, startX, startpoint);
          break;
        }
        startpoint = startpoint + steps;
      }
    }
  }
  1. 然后就是下载图片下载图片
  // 下载图片
  addImage() {
    wx.canvasToTempFilePath({
      canvas: this.data.canvas, // canvas 实例
      success(res) {
        console.log(res);
        // canvas 生成图片成功
        wx.saveImageToPhotosAlbum({
          filePath: res.tempFilePath,
          success(res) {
            // 保存成功
            wx.showToast({
              title: '已保存相册',
              icon: 'success',
              duration: 2000
            })
          }
        })
      }
    })
  }
  1. 完整代码
Page({
  data: {
    imageUrl: 'https://img2.baidu.com/it/u=1884974821,3634354042&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=679',
    title: '扫描二维码,加入我们,新人优惠,特价商品',
    code: '/static/1686968496385.jpg',
    isFlag: false
  },
  generatePosters() {
    this.setData({
      isFlag: !this.data.isFlag
    })
    const query = wx.createSelectorQuery()
    query.select('#myCanvas')
      .fields({
        node: true,
        size: true
      })
      .exec((res) => {
        const canvas = res[0].node
        const ctx = canvas.getContext('2d')
        const dpr = wx.getSystemInfoSync().pixelRatio
        // 将画布大小按照设备像素比例进行调整,使其在不同设备上显示的效果更加一致。
        canvas.width = res[0].width * dpr
        canvas.height = res[0].height * dpr
        ctx.scale(dpr, dpr)
        const bg = canvas.createImage()
        bg.src = this.data.imageUrl
        bg.onload = () => {
          ctx.drawImage(bg, 0, 0, 300, 400)
        }
        // 绘制 底部 盒子
        ctx.fillStyle = '#f0f0f0'
        ctx.fillRect(0, 400, 500, 100)
        ctx.fill()
        // 设置 字体
        ctx.fillStyle = '#000'
        ctx.font = "16px 楷体"
        this.toFormateStr(ctx, this.data.title, 160, 5, 12, 450, 20)
        // 生成 二维码
        const code = canvas.createImage()
        code.src = this.data.code
        code.onload = () => {
          ctx.drawImage(code, 220, 420, 60, 60)
        }
        this.setData({
          canvas: canvas
        })
      })
  },
  /**
   *  参数解析:
   * 	ctx:  canvas绘图上下文
   * 	str:  需要绘制的文本内容
   * 	draw_width:  绘制后的文字显示宽度
   * 	lineNum:  最大行数,多出部分用'...'表示, 如果传-1可以达到自动换行效果
   * 	startX:  绘制文字的起点 X 轴坐标
   * 	startY:  绘制文字的起点 Y 轴坐标
   *	steps:  文字行间距
   */
  toFormateStr(ctx, str, draw_width, lineNum, startX, startY, steps) {
    let strWidth = ctx.measureText(str).width; // 测量文本源尺寸信息(宽度)
    let startpoint = startY,
      keyStr = '',
      sreLN = strWidth / draw_width; // 文本长度除以换行的宽 得到一共生成多少行
    let liner = Math.ceil(sreLN); // 计算文本源一共能生成多少行
    let strlen = parseInt(str.length / sreLN); // 等比缩放测量一行文本显示多少个字符
    // 若文本不足一行,则直接绘制,反之大于传入的最多行数(lineNum)以省略号(...)代替
    if (strWidth < draw_width) {
      ctx.fillText(str, startX, startpoint);
    } else {
      for (let i = 1; i < liner + 1; i++) {
        let startPoint = strlen * (i - 1);
        if (i < lineNum || lineNum == -1) {
          keyStr = str.substr(startPoint, strlen);
          ctx.fillText(keyStr, startX, startpoint);
        } else {
          keyStr = str.substr(startPoint, strlen - 5) + '...';
          ctx.fillText(keyStr, startX, startpoint);
          break;
        }
        startpoint = startpoint + steps;
      }
    }
  },
  // 下载图片
  addImage() {
    wx.canvasToTempFilePath({
      canvas: this.data.canvas, // canvas 实例
      success(res) {
        console.log(res);
        // canvas 生成图片成功
        wx.saveImageToPhotosAlbum({
          filePath: res.tempFilePath,
          success(res) {
            // 保存成功
            wx.showToast({
              title: '已保存相册',
              icon: 'success',
              duration: 2000
            })
          }
        })
      }
    })
  }
})

.fs

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值