小程序 canvas 使用

这段代码展示了如何在微信小程序中使用canvas进行图像合成,包括绘制背景图、图标、文字等,并最终保存图片到相册。它涉及到wx.createCanvasContext、drawImage等方法,以及动态调整比例以适配不同屏幕尺寸。
摘要由CSDN通过智能技术生成
handleSavePhoto(e) {
    let item = e.currentTarget.dataset.item
    let that = this
    const qrContainer = this.selectComponent("#qrcodeCom")
    let imageUrl = qrContainer.getQrFile()
    let scale =
    this.data.windowWidth / 375.0 <= 1 ?
      1 :
      Math.floor(this.data.windowWidth / 375.0);


    wx.showLoading({
      title: '正在保存中',
    })

    let ctx = wx.createCanvasContext('canvasPoster')
    ctx.scale(this.data.canvasScale, this.data.canvasScale)
    that.setData({
      ctx,
      popWidth: 638 * scale,
      popHeight: 1107 * scale,
    })
    ctx.setFillStyle('#ffffff')
    ctx.fillRect(0, 0, that.data.popWidth, that.data.popHeight)
    ctx.draw()

    let icon = 'https://yizhen-mamapai-dev.oss-cn-zhangjiakou.aliyuncs.com/certification/2023-06-16/3dfa4c629e34474ca3ea9275206e8b0e.png'
    let btnIcon = 'https://yizhen-mamapai-dev.oss-cn-zhangjiakou.aliyuncs.com/certification/2023-06-25/c65d68d5dbee47ca8630b18a54290838.png'
    let btnIcon2 = 'https://yizhen-mamapai-dev.oss-cn-zhangjiakou.aliyuncs.com/certification/2023-06-25/2d7e75b103e64751a9b8df8268f5a734.png'
    const imgUrl = 'https://yizhen-mamapai-dev.oss-cn-zhangjiakou.aliyuncs.com/certification/2023-06-29/d0bbe1bc9cc2441784a317ad14b0320b.png';

    /** 先画背景图在背景图上画内容 */
    wx.getImageInfo({
      src: imgUrl,
      success: (res) => {
        if (res.errMsg = 'getImageInfo:ok') {
          ctx.drawImage(res.path, 0 * scale, 0 * scale, this.data.popWidth * scale, 1107 * scale)
          ctx.draw(true)

          // 画icon
          this.drawActiveTags(ctx, scale, icon)

          //画提示 
          this.drawNormalText(ctx, item.popName, (this.data.popWidth / 2 + 20) * scale, 200 * scale, 30 * scale, '#FF2912', 'center', 'middle', scale)

          let itemText = item.popDescribe.replace(/[ \r\n]+/g, '')
          // 画内容
          this.textPrewrap(ctx, itemText, (this.data.popWidth / 2) * scale, 260 * scale, 50 * scale, 360 * scale, 3, '#FF2912')

          //画 title
          this.drawNormalText(ctx, item.popCodeDescribe, (this.data.popWidth / 2) * scale, 410 * scale, 30 * scale, '#333333', 'center', 'middle', scale)

          // 画 qrcode
          this.drawLogo(imageUrl, ctx, scale)

          //画按钮
          this.drawerDetailImg(ctx, scale, btnIcon, 52, 860, 534, 104)

          // 画内容
          this.drawNormalText(ctx, item.saveButtonName, (this.data.popWidth / 2) * scale, 915 * scale, 30 * scale, '#4CAFF4', 'center', 'middle', scale)

          //画按钮
          this.drawerDetailImg(ctx, scale, btnIcon2, 52, 980, 534, 104, item)
        }
      }
    })
    setTimeout(() => {
      ctx.draw(true, () => {
        this.getCanvasImg()
      })
    }, 1000)
  },
  
  // 保存图片
  saveImageToPhotos: function (tempFilePath) {
    wx.saveImageToPhotosAlbum({
      filePath: tempFilePath,
      success(result) {
        console.log(result, 'result')
        wx.showToast({
          title: '保存成功,从相册中分享给朋友吧',
          icon: 'none',
          duration: 4000
        })
      },
      fail: function (res) {
        wx.showToast({
          title: '图片保存失败',
          icon: 'none',
          duration: 2000
        })
      }
    })
  },
  
  // 获取生成的canvas图片
  getCanvasImg() {
    let that = this
    wx.canvasToTempFilePath({
      x: 0,
      y: 0,
      width: that.data.popWidth * that.data.canvasScale,
      height: that.data.popHeight * that.data.canvasScale,
      canvasId: 'canvasPoster',
      success: function (res) {
        wx.hideLoading()
        // 保存本地
        that.saveImageToPhotos(res.tempFilePath);
      },
      fail: function (res) {
        wx.hideLoading()
        wx.showToast({
          title: '图片生成失败',
          icon: 'none',
          duration: 2000
        })
      }
    })
  },
  
    // 绘制只有一行的文字
  drawNormalText(ctx, str, x, y, font, style, align, baseLine) {
    ctx.setFontSize(font);
    ctx.setFillStyle(style);
    ctx.setTextAlign(align);
    ctx.setTextBaseline(baseLine);
    ctx.fillText(str, x, y);
  },
  /*
    *  绘制多行文本,自动换行,超出添加...
    *
    content:要绘制的字符串
    ctx:canvas对象
    drawX:绘制字符串起始x坐标
    drawY:绘制字符串起始y坐标
    lineHeight:字行高,自己定义个值即可
    lineMaxWidth: 文本最大宽度
    lineNum: 最大行数
    */
  textPrewrap(ctx, content, drawX, drawY, lineHeight, lineMaxWidth, lineNum, style) {
    ctx.setFillStyle(style);
    var drawTxt = ''; // 当前绘制的内容
    var drawLine = 1; // 第几行开始绘制
    var drawIndex = 0; // 当前绘制内容的索引
    // 判断内容是否可以一行绘制完毕
    if (ctx.measureText(content).width <= lineMaxWidth) {
      ctx.fillText(content.substring(drawIndex, i), drawX, drawY);
    } else {
      for (var i = 0; i < content.length; i++) {
        drawTxt += content[i];
        if (ctx.measureText(drawTxt).width >= lineMaxWidth) {
          if (drawLine >= lineNum) {
            ctx.fillText(content.substring(drawIndex, i) + '..', drawX, drawY);
            break;
          } else {
            ctx.fillText(content.substring(drawIndex, i + 1), drawX, drawY);
            drawIndex = i + 1;
            drawLine += 1;
            drawY += lineHeight;
            drawTxt = '';
          }
        } else {
          // 内容绘制完毕,但是剩下的内容宽度不到lineMaxWidth
          if (i === content.length - 1) {
            ctx.fillText(content.substring(drawIndex), drawX, drawY);
          }
        }
      }
    }
  },
  //画logo
  drawLogo(imageUrl, ctx, scale) {
    const logoUrl = imageUrl;
    wx.getImageInfo({
      src: logoUrl,
      success: (res) => {
        console.log(res)
        if (res.errMsg = 'getImageInfo:ok') {
          ctx.drawImage(imageUrl, (this.data.popWidth / 2 - 170) * scale, (this.data.popHeight / 2 - 80) * scale, 338 * scale, 338 * scale)
          ctx.draw(true)
        }
      }
    })
  },
  // icon
  drawActiveTags(ctx, scale, icon) {
    const tagsUrl = icon;
    wx.getImageInfo({
      src: tagsUrl,
      success: (res) => {
        if (res.errMsg = 'getImageInfo:ok') {
          ctx.drawImage(res.path, (this.data.popWidth / 2 - 90) * scale, 180 * scale, 30 * scale, 30 * scale)
          ctx.draw(true)
        }
      }
    })
  },
  /**
   * @param {画布信息} ctx 
   * @param {缩放大小} scale 
   * @param {icon} icon 
   * @param {横} x 
   * @param {竖} y 
   * @param {宽} w 
   * @param {高} h 
   */
  // 活动详情图片
  drawerDetailImg(ctx, scale, icon, x, y, w, h, item) {
    let that = this
    const detailUrl = icon;
    console.log(this.data)
    wx.getImageInfo({
      src: detailUrl,
      success: (res) => {
        console.log(res, '画详情')
        if (res.errMsg = 'getImageInfo:ok') {
          ctx.drawImage(res.path, x * scale, y * scale, w * scale, h * scale)
          if (item) {
            // 画内容
            this.drawNormalText(ctx, item.scanCodeName, (this.data.popWidth / 2) * scale, 1035 * scale, 30 * scale, '#ffffff', 'center', 'middle', scale)
          }
          ctx.draw(true)
        }
      },
      fail: (err) => {
        console.log(err)
      }
    })
  },

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值