小程序 自定义二维码 canvas海报 canvas保存为本地图片

预设画板跟预览保存图片

// html<canvas canvas-id="shareImg" class="canvas-exp"></canvas>
<view hidden=‘{{previewHidden}}‘ class=‘preview‘>
  <image src=‘{{preurl}}‘ mode=‘widthFix‘ class=‘previewImg‘></image>
  <view class="flex-justify-between btns">
    <button bindtap=‘save‘ class="themeBtn themeColor btns-open">保存到相册</button>
  </view>
  <image src="/assets/icon_closed_white.png" class="cler" bindtap="remove"></image>
</view>CSS

/* //海报 */
.poster{
  background:#fff;font-size:32rpx;
  margin: 10rpx auto;
}
.canvas-exp{
  position: fixed;
  bottom: 0;
  right: 100%;
  width:100%;height:606px;background:#fff;
}
.preview {
  width: 100%;
  height: 100%;
  background: rgba(0,0,0,1);
  position:fixed;
  top: 0;
  left: 0;
  z-index: 2;
}
.previewImg{
  width: 88%;
  position: absolute;
  top: 100rpx;
  left: 6%;
  z-index: 3;
  border: 1px solid #000;
  border-radius: 5px;
  max-height: 800rpx;
}
.preview button{
  width: 78%;
  position: absolute;
  top: 960rpx;
  left: 11%;
  border-radius: 2px;
}
.preview .cler{
  width: 64rpx;
  height: 64rpx;
  position: absolute;
  top: 1100rpx;
  left: 50%;
  margin-left: -32rpx;
}

获取后端生成的小程序码 利用 wx.downloadFile 下载到本地 主要是因为小程序canvas 不支持远程图片 

获取后根据要求进行排版绘制 另外文字换行使用自定义函数

//canvas 海报
  createCanvasContext() {
    let that = this
    let winWidth = wx.getSystemInfoSync().windowWidth; // 获取当前设备的可视宽度
    let winHeight = wx.getSystemInfoSync().windowHeight; // 获取当前设备的可视高度
    that.setData({
      winWidth: winWidth,
      winHeight: winHeight
    })
    let imageUrl = that.data.articleData.coverPicture
    wx.downloadFile({
      url: imageUrl,
      success(res) {
        if (res.statusCode === 200) {
          imageUrl = res.tempFilePath
        } else {
          imageUrl = ‘/assets/lA.png‘
        }
      },fail(){
        imageUrl = ‘/assets/lA.png‘
      }
    })
    let userNick = ‘90%的备孕人士都在看的精品好‘,
        userNick2 = ‘文,‘,
        userNick3 = ‘长按识别‘,
        userNick4 = ‘小程序阅读全文‘;
    let contentTitle = that.data.articleData.title || ‘文章标题‘
    let scene = that.data.channelCode + ‘,‘ + that.data.userCode
    let data = {
      page: ‘pages/hotinfo/hotinfo‘,
      sceneStr: scene
    }
    // 生成小程序码
    call.httpService(‘share/generateAppletCode‘, data, ‘post‘, (elem)=>{
      console.log(elem)
      if (elem.code == 0){
        let imgPath = elem.data
          wx.downloadFile({
            url: imgPath,
            success(res) {
              console.log(res)
              if (res.statusCode === 200) {
                imgPath = res.tempFilePath
                const ctx = wx.createCanvasContext(‘shareImg‘)
                ctx.setFillStyle(‘#fff‘)
                ctx.fillRect(0, 0, winWidth, 800)
                ctx.drawImage(imageUrl, 0, 0, winWidth, 228 * Rpx)
                var currentLineHeight = 228 * Rpx + 10;
                ctx.setTextAlign(‘left‘)
                ctx.setFillStyle(‘#2E2F2F‘)
                ctx.setTextAlign(‘left‘)
                let row = util.measureTexts(ctx, contentTitle, winWidth)
                ctx.font = ‘normal bold 18px sans-serif‘;
                for (var b = 0; b < row.length; b++) {
                  currentLineHeight += Rpx * 30;
                  ctx.fillText(row[b], 15, currentLineHeight);
                }
                if (row.length==1){
                  currentLineHeight += 5 * Rpx 
                }
                currentLineHeight += 85 * Rpx 
                ctx.font = ‘normal 100 15px sans-serif‘;
                ctx.setFillStyle(‘#828282‘) 
                
                ctx.fillText(userNick, 25, currentLineHeight);
                currentLineHeight += Rpx * 20;
                ctx.fillText(userNick2, 25, currentLineHeight);
                ctx.setFillStyle(‘#FF951A‘)
                ctx.fillText(userNick3, 25 + ctx.measureText(userNick2).width, currentLineHeight);
                ctx.setFillStyle(‘#828282‘) 
                ctx.fillText(userNick4, 25 + ctx.measureText(userNick2).width + ctx.measureText(userNick3).width, currentLineHeight);
                ctx.setFillStyle(‘#185C58‘)
                ctx.fillRect(15, currentLineHeight - (Rpx * 20 * 2 - 10 * Rpx), 2, Rpx * 20 * 2 - 10 * Rpx)

                ctx.drawImage(imgPath, winWidth - 105 * Rpx, currentLineHeight-80, 90, 90)
                currentLineHeight += 25 * Rpx
                ctx.stroke()
                ctx.draw()
                that.setData({
                  imgPath: imgPath,
                  currentLineHeight: currentLineHeight
                })
                if(that.data.createShow){
                  setTimeout(() => {
                    that.share()
                  }, 800);
                }
              } else {
                wx.showToast({
                  title: ‘数据加载失败‘,
                  icon: ‘none‘,
                  duration: 2000
                })
              }
            }, fail(res) {
              wx.showToast({
                title: ‘数据加载失败!‘,
                icon: ‘none‘,
                duration: 2000
              })
            }
          })
        }else{
          wx.showToast({
            title: ‘数据加载失败‘,
            icon: ‘none‘,
            duration: 2000
          })
        }
    }, (err)=>{

    }, false)
  },

 save: function() {
    var that = this;
    //获取相册授权
    wx.getSetting({
      success(res) {
        if (!res.authSetting[‘scope.writePhotosAlbum‘]) {
          wx.authorize({
            scope: ‘scope.writePhotosAlbum‘,
            success() {
              that.savaImageToPhoto();
            }
          })
        } else {
          that.savaImageToPhoto();
        }
      }
    })
  },
  /**
   * 生成分享图
   */
  share: function() {
    var that = this
    wx.showLoading({
      title: ‘努力生成中...‘
    })
    wx.canvasToTempFilePath({
      x: 0,
      y: 0,
      width: this.data.winWidth,
        height: this.data.currentLineHeight,
        destWidth: this.data.winWidth*2,
        destHeight: this.data.currentLineHeight*2,
        canvasId: ‘shareImg‘,
      success: function(res) {
        console.log(res.tempFilePath);
        that.setData({
          preurl: res.tempFilePath,
          previewHidden: false,
        })
        wx.hideLoading()
      },
      fail: function(res) {
        console.log(res)
      }
    })
  },
  savaImageToPhoto: function() {
    let that = this;
    wx.saveImageToPhotosAlbum({
      filePath: that.data.preurl,
      success(res) {
        that.setData({
          previewHidden: true
        })
        wx.showToast({
          title: ‘已保存到相册‘,
          icon: ‘success‘,
          duration: 2000
        })
      }
    })
  },
 
util.js
const measureTexts = (ctx, contentTitle, winWidth) => {
  var chr = contentTitle.split(""); //这个方法是将一个字符串分割成字符串数组
  var temp = "";
  var row = [];
  for (var a = 0; a < chr.length; a++) {
    if (ctx.measureText(temp).width < winWidth / 2 - 10) {
      temp += chr[a];
    } else {
      a--; //这里添加了a-- 是为了防止字符丢失,效果图中有对比
      row.push(temp);
      temp = "";
    }
  }
  row.push(temp);
  //如果数组长度大于2 则截取前两个
  if (row.length > 2) {
    var rowCut = row.slice(0, 2);
    var rowPart = rowCut[1];
    var test = "";
    var empty = [];
    for (var a = 0; a < rowPart.length; a++) {
      if (ctx.measureText(test).width < winWidth / 2 - 10) {
        test += rowPart[a];
      } else {
        break;
      }
    }
    empty.push(test);
    var group = empty[0] + "..." //这里只显示两行,超出的用...表示
    rowCut.splice(1, 1, group);
    row = rowCut;
  }
  return row
}
module.exports = {
  measureTexts: measureTexts
}

效果大概如下  

 

相关推荐