微信小程序通过canvas生成二维码分享海报

831 阅读3分钟

通过微信小程序的canvas生成分享海报 放置海报的 canvas

      <canvas
        v-show="false"
        class="canvas"
        type="2d"
        id="myCanvas"
        style="width: 622rpx; height: 858rpx"
      ></canvas>

data内容

 data () {
       return {
          show: false, //控制显示海报的弹窗的变量
          imageShow: false, //控制海报显示的变量
          url: '', //海报路径
          qr_code: '', //二维码路径
       }
    },

点击生成海报函数

developers.weixin.qq.com/miniprogram…

image.png

   
    handleSharp() {
    //这是控制显示海报的弹窗控件
      this.show = true
      uni.showLoading({
        title: '生成分享海报中...',
      })
      //this 重新赋值 因为下面的函数中this指针会改变
      const that = this
     //获取canvas的dome节点
      const query = uni.createSelectorQuery().in(this)
      query
        .select('#myCanvas')
        .fields({
          node: true,
          size: true,
        })
        .exec((res) => {
          //#region  获取节点,设置像素
          const canvas = res[0].node
          const ctx = canvas.getContext('2d')
          //  绘制前,先清空上一次的绘制
          ctx.clearRect(0, 0, canvas.width, canvas.height)
          //获取设备像素比
          const dpr = wx.getSystemInfoSync().pixelRatio
          canvas.width = 622 * dpr
          canvas.height = (858 - 64) * dpr
          ctx.scale(dpr, dpr)
          //#endregion
          //绘制网络图片时,要先下载 ,通过 uni.downloadFile下载
          uni
            .downloadFile({
              url: 'https://img2.baidu.com/it/u=1441022992,3594689583&fm=253&fmt=auto&app=120&f=JPEG?w=1422&h=800',
            })
            .then(async (res) => {
            获取二维码的图片路径
              await that.handleQrcode()
              //#region 创建图片对象
              const img = canvas.createImage()
              img.src = res[1].tempFilePath
              //#endregion
              img.onload = () => {
              //图片加载完通过drawImage绘制上去
                ctx.drawImage(img, 0, 0, 622, 318)
                //绘制放置海报内容盒子的函数
                that.handleCanvas(0, 264, 622, 562, 32, ctx)
                //绘制放置海报内容的函数
                that.handleCanvasText(ctx, '这是内容', 40, 336, 36, '#000000')
                //绘制放置二维码的图片对象
                const img_qrcode = canvas.createImage()
                img_qrcode.src = that.qr_code
                img_qrcode.onload = function () {
                  ctx.drawImage(img_qrcode, 40, 600, 120, 120)
                  //生成临时路径的api 方便通过image在页面显示和下载
                  wx.canvasToTempFilePath({
                    x: 0,
                    y: 0,
                    width: 622,
                    height: 858 - 64,
                    destWidth: 622 * dpr,
                    destHeight: 858 * dpr,
                    canvasId: 'myCanvas',
                    canvas: canvas,
                    success(res) {
                      console.log('海报临时路径为:', res.tempFilePath)
                      that.url = res.tempFilePath
                      that.imageShow = true
                      //关闭loading
                      uni.hideLoading()
                    },
                    fail(res) {
                      console.error(res)
                    },
                  })
                }
              }
            })
          // await that.handleQrcode()
          // ctx.drawImage(img, 0, 0, 622, 318)
          // }
        })
    },

二维码canvas 通过插件生成二维码 npm i weapp-qrcode-canvas-2d

      <canvas
        v-show="false"
        type="2d"
        style="width: 120rpx; height: 120rpx"
        id="myQrcode"
      ></canvas>

获取二维码的函数

//引入插件
import drawQrcode from 'weapp-qrcode-canvas-2d'
    handleQrcode() {
      return new Promise((resolve, reject) => {
        const that = this
        const query = uni.createSelectorQuery().in(this)
        query
          .select('#myQrcode')
          .fields({
            node: true,
            size: true,
          })
          .exec((res) => {
            const canvas = res[0].node
            const ctx = canvas.getContext('2d')
            ctx.clearRect(0, 0, canvas.width, canvas.height)
            uni
              .downloadFile({
                url: 'https://hr-zhoushuren-1312551878.cos.ap-guangzhou.myqcloud.com/0203r1200092xxh1mA5E2_W_1080_808_R5_D.png',
              })
              .then((res) => {
                const img = canvas.createImage()
                img.src = res[1].tempFilePath
                //#endregion
                img.onload = () => {
                  var options = {
                    canvas: canvas,
                    canvasId: 'myQrcode',
                    width: 260,
                    padding: 30,
                    paddingColor: '#fff',
                    background: '#fff',
                    foreground: '#000000',
                    text: '内容',
                    image: {
                      imageResource: img,
                      width: 80, // 建议不要设置过大,以免影响扫码
                      height: 80, // 建议不要设置过大,以免影响扫码
                      round: true, // Logo图片是否为圆形
                    },
                  }
                  drawQrcode(options)
                  // 获取临时路径
                  wx.canvasToTempFilePath({
                    x: 0,
                    y: 0,
                    width: 260,
                    height: 260,
                    destWidth: 600,
                    destHeight: 600,
                    canvasId: 'myQrcode',
                    canvas: canvas,
                    success(res) {
                      console.log('二维码临时路径为:', res.tempFilePath)
                      that.qr_code = res.tempFilePath
                      resolve()
                    },
                    fail(res) {
                      reject(res)
                    },
                  })
                }
              })
          })
      })
    },

海报内容盒子的函数

    //传递参数分别为 x坐标,y坐标,宽度,高度,半径,canvas上下文(即canvas节点)
    handleCanvas(x, y, w, h, r, ctx) {
      // 设置填充色
      ctx.fillStyle = '#fff'
      // 绘制圆角矩形
      ctx.moveTo(x + r, y)
      ctx.lineTo(x + w - r, y)
      ctx.arc(x + w - r, y + r, r, -Math.PI / 2, 0)
      ctx.lineTo(x + w, y + h - r)
      // ctx.arc(x + w - r, y + h - r, r, 0, Math.PI / 2)
      ctx.lineTo(x, y + h - r)
      // ctx.arc(x + r, y + h - r, r, Math.PI / 2, Math.PI)
      // ctx.lineTo(x, y + r)
      ctx.arc(x + r, y + r, r, Math.PI, (Math.PI * 3) / 2)
      // 填充圆角矩形
      ctx.fill()
    },

海报文字内容函数

    //传递参数分别为 canvas上下文(即canvas节点),文字内容,x坐标,y坐标,字体大小,颜色
    handleCanvasText(ctx, text, x, y, size, color) {
      let newText = text
      let chr = newText.split('')
      let temp = ''
      let row = []
      ctx.font = `${size}px Arial`
      ctx.fillStyle = color
      for (var a = 0; a < chr.length; a++) {
        if (ctx.measureText(temp).width < 542) {
          temp += chr[a]
        } else {
          a-- //这里添加了a-- 是为了防止字符丢失,效果图中有对比
          row.push(temp)
          temp = ''
        }
      }
      row.push(temp)
      if (row.length > 3) {
        var rowCut = row.slice(0, 3)
        var rowPart = rowCut[2]
        var test = ''
        var empty = []
        for (var a = 0; a < rowPart.length; a++) {
          if (ctx.measureText(test).width < 220) {
            test += rowPart[a]
          } else {
            break
          }
        }
        empty.push(test)
        var group = empty[0] + '...' //这里只显示两行,超出的用...表示
        rowCut.splice(2, 1, group)
        row = rowCut
      }
      for (var b = 0; b < row.length; b++) {
        ctx.fillText(row[b], x, y + b * (size + 10))
      }
    },
  },

展示效果

image.png

以上微信api如果不起作用,大概率是微信api淘汰了,请去微信官方文档查阅 developers.weixin.qq.com/miniprogram…

如有错漏,请指出评论

受教了