• 微信小程序利用canvas生成海报分享图片


    一 . 效果

     这是借用女神照生成的分享的海报,图片来自网络。

    新增了poster组件和更新图片自适应

    二 . 准备

     准备两张图片连接,最好是自己开发账号验证的https图片链接。
    

    三 . 实现思路

    其实就是canvas实现方式,首先要就是定义一个canvas容器,把容器放在中间,图片也要动态计算大小居中,显示下面的文字和二维码也是要根据容器动态去改变,这就是大概的实现思路。

    四 . 实现代码

    利用微信小程序canvas生成海报分享图片,这个生成图片排版和适配不同尺寸的手机是一个难点,特别是图片适应问题,我处理的方法是动态获取容器的宽度进行适应就是利用微信API wx.createSelectorQuery(),不知道还有没有更好的办法可以请教。

    1.下载头像
    为了确保图片下载完成之后,再回调其它方法执行下一步。


    getAvaterInfo: function (cardInfo) {//cardInfo是传入的信息参数,按实际需要。
        wx.showLoading({ title: '生成中...',mask: true,});
        var that = this;
        if (cardInfo.CardInfo.Avater) {
          wx.downloadFile({
            url: '图片路径',
            success: function (res) {
              wx.hideLoading();
              if (res.statusCode === 200) {
                var avaterSrc = res.tempFilePath;
                that.getQrCode(avaterSrc, cardInfo);
              }else{
                wx.showToast({
                  title: '头像下载失败!',
                  icon:'none',
                  duration: 2000,
                  success:function(){
                    that.getQrCode(avaterSrc = "", cardInfo);//回调另一个图片下载
                  }
                })
              }
            }
          })
        } else {
          wx.hideLoading();
          that.getQrCode(avaterSrc = "", cardInfo);//回调另一个图片下载
        }
      },
    

      2.下载二维码
    二维码下载一样的道理,就是先下载完成,再进行绘图。

     getQrCode: function (avaterSrc, cardInfo) {
        wx.showLoading({ title: '生成中...', mask: true, });
        var that = this;
        if (cardInfo.CardInfo.QrCode) {
          wx.downloadFile({
            url: cardInfo.CardInfo.QrCode,
            success: function (res) {
              wx.hideLoading();
              if (res.statusCode === 200) {
                var codeSrc = res.tempFilePath;
                that.sharePosteCanvas(cardInfo, avaterSrc, codeSrc);//真正的绘图方法
              } else {
                wx.showToast({
                  title: '二维码下载失败!',
                  icon: 'none',
                  duration: 2000,
                  success: function () {
                    var codeSrc  = "";
                    that.sharePosteCanvas(cardInfo, avaterSrc, codeSrc);//真正的绘图方法
                  }
                })
              }
            }
          })
        } else {
          wx.hideLoading();
         var codeSrc  = "";
          that.sharePosteCanvas(cardInfo, avaterSrc, codeSrc);//真正的绘图方法
        }
      },
    

      3.绘制分享海报
    这里才是canvas实现绘制的过程

    sharePosteCanvas: function (cardInfo, avaterSrc, codeSrc) {
        wx.showLoading({
          title: '生成中...',
          mask: true,
        })
        var that = this;
        const ctx = wx.createCanvasContext('myCanvas');
        var width = "";
        wx.createSelectorQuery().select('#canvas-container').boundingClientRect(function (rect) {
          var height = rect.height;
          var right = rect.right;
          width = rect.width * 0.8;
          var left = rect.left + 5;
          ctx.setFillStyle('#fff');
          ctx.fillRect(0, 0, rect.width, height);
    
          //头像
          if (avaterSrc) {
            ctx.drawImage(avaterSrc, left, 20, width, width);
            ctx.setFontSize(14);
            ctx.setFillStyle('#fff');
            ctx.setTextAlign('left');
          }
    
          if (cardInfo.TagList.length > 0) {
            ctx.fillText(cardInfo.TagList[0].TagName, left + 20, width - 4); //标签
            const metrics = ctx.measureText(cardInfo.TagList[0].TagName); //测量文本信息
            ctx.stroke();
            ctx.rect(left + 10, width - 20, metrics.width + 40, 25);
            ctx.setFillStyle('rgba(255,255,255,0.4)');
            ctx.fill();
          }
    
          if (cardInfo.CardInfo.Name) {
            ctx.setFontSize(14);
            ctx.setFillStyle('#000');
            ctx.setTextAlign('left');
            ctx.fillText(cardInfo.CardInfo.Name, left, width + 60); //姓名
          }
    
          if (cardInfo.CardInfo.Position) {
            ctx.setFontSize(12);
            ctx.setFillStyle('#666');
            ctx.setTextAlign('left');
            ctx.fillText(cardInfo.CardInfo.Position, left, width + 85); //职位
          }
    
          if (cardInfo.CardInfo.Mobile) {
            ctx.setFontSize(12);
            ctx.setFillStyle('#666');
            ctx.setTextAlign('left');
            ctx.fillText(cardInfo.CardInfo.Mobile, left, width + 105); //电话
          }
    
          if (cardInfo.CardInfo.Company) {
            // 公司名称
            const CONTENT_ROW_LENGTH = 24; // 正文 单行显示字符长度
            let [contentLeng, contentArray, contentRows] = that.textByteLength(cardInfo.CardInfo.Company, CONTENT_ROW_LENGTH);
            ctx.setTextAlign('left');
            ctx.setFillStyle('#000');
            ctx.setFontSize(10);
            let contentHh = 22 * 1;
            for (let m = 0; m < contentArray.length; m++) {
              ctx.fillText(contentArray[m], left, width + 150 + contentHh * m);
            }
          }
    
          //  绘制二维码cardInfo.CardInfo.QrCode
          if (codeSrc) {
            ctx.drawImage(codeSrc, left + 150, width + 40, width / 3, width / 3)
            ctx.setFontSize(10);
            ctx.setFillStyle('#000');
            ctx.setTextAlign('right');
            ctx.fillText("微信扫码或长按识别", left + 235, width + 150);
          }
    
        }).exec()
    
        setTimeout(function () {
          ctx.draw();  这里有个需要注意就是,这个方法是在绘制完成之后在调用,不然容易其它被覆盖。
          wx.hideLoading();
        }, 1000)
    
      },
    

      4.多行显示文字
    这个函数就是需要多行显示文字的时候进行折行,就是切分为数组。

    textByteLength(text, num) { // text为传入的文本  num为单行显示的字节长度
        let strLength = 0; // text byte length
        let rows = 1;
        let str = 0;
        let arr = [];
        for (let j = 0; j < text.length; j++) {
          if (text.charCodeAt(j) > 255) {
            strLength += 2;
            if (strLength > rows * num) {
              strLength++;
              arr.push(text.slice(str, j));
              str = j;
              rows++;
            }
          } else {
            strLength++;
            if (strLength > rows * num) {
              arr.push(text.slice(str, j));
              str = j;
              rows++;
            }
          }
        }
        arr.push(text.slice(str, text.length));
        return [strLength, arr, rows] //  [处理文字的总字节长度,每行显示内容的数组,行数]
      },
    

      5.保存绘制生成图片
    这一步就是最后把canvas生成图片了,大功告成。

     //点击保存到相册
      saveShareImg: function () {
        var that = this;
        wx.showLoading({
          title: '正在保存',
          mask: true,
        })
        setTimeout(function () {
          wx.canvasToTempFilePath({
            canvasId: 'myCanvas',
            success: function (res) {
              wx.hideLoading();
              var tempFilePath = res.tempFilePath;
              wx.saveImageToPhotosAlbum({
                filePath: tempFilePath,
                success(res) {
                  wx.showModal({
                    content: '图片已保存到相册,赶紧晒一下吧~',
                    showCancel: false,
                    confirmText: '好的',
                    confirmColor: '#333',
                    success: function (res) {
                      if (res.confirm) { }
                    },
                    fail: function (res) { }
                  })
                },
                fail: function (res) {
                  wx.showToast({
                    title: res.errMsg,
                    icon: 'none',
                    duration: 2000
                  })
                }
              })
            }
            });
              }, 1000);
           },
    

      

    五 . 填坑

    1.图片要提前下载
    这里面还有一个问题就是,图片要提前下载完之后再绘图,不然图片显示不出来,可以把下载图片的方法单独拎出来,然后下载图片后回调绘图方法。

    1. ctx.draw()
      这个方法是在绘制完成之后在调用,不然容易其它被覆盖。

    这样就大功告成了,有问题可以和联系作者,一起进步。
    喜欢就点点喜欢鼓励
    DEMO路径:https://github.com/kingbuwu/poster
    demo上封装了poster组件和显示头图图片自适应



    
    
  • 相关阅读:
    1132: 零起点学算法39——多组测试数据(a+b)
    1131: 零起点学算法38——求阶乘和
    1130: 零起点学算法37——求阶乘
    1129: 零起点学算法36——3n+1问题
    1128: 零起点学算法35——再求多项式(含浮点)
    1127: 零起点学算法34——继续求多项式
    1126: 零起点学算法33——求多项式
    Netty源码分析第1章(Netty启动流程)---->第1节: 服务端初始化
    Netty源码分析(前言, 概述及目录)
    基于HTK语音工具包进行孤立词识别的使用教程
  • 原文地址:https://www.cnblogs.com/yehuisir/p/10800135.html
Copyright © 2020-2023  润新知