小程序 生成自定義小程序二維碼碼 通過 canvas 生成海報 保存成圖片


功能很簡單 直接上代碼

 

html

canvas 定義畫板 構造海報  .preview 生成海報圖瀏覽 模板框 

<canvas canvas-id="shareImg" class="canvas-exp"></canvas>
<view hidden='{{previewHidden}}' class='preview'>
  <image src='{{preurl}}' mode='widthFix' class='previewImg'></image>
  <button type='primary' bindtap='save' style="background:#0A655A">保存到本地</button>
</view>
 
<view class="shares-btn">
  <button class="share" bindtap="share">
    <image src="images/icon_share.png" style="width:36rpx;" mode="widthFix"></image>
    <view class="share-title">分享</view>
  </button>
</view>

css


.canvas-exp{
  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;
}
.shares-btn{
  position: fixed;
  right: 20rpx;
  top: 20%;
  z-index: 101;
  transition: all 0.5s;
}
.share{
  width: 100rpx;
  height: 100rpx;
  background-color: #007aff;
  border-radius: 50%;
  color: #fff;
  font-size: 26rpx;
  padding: 0;
}
.share-title{
  margin-top: -14px;
  font-size:24rpx;
}
p{
  padding: 0;
  margin: 0;
}

核心代碼 js

 

// pages/all/index.js
Page({

  /**
   * 頁面的初始數據
   */
  data: {
    currentLineHeight: 0,
    previewHidden: true 
  },
  onLoad(){
    this.createCanvasContext()

  },
  createCanvasContext() {
    let that =this
    var expiration = wx.getStorageSync("index_data_expiration"); //拿到過期時間
    var timestamp = Date.parse(new Date()); //拿到現在時間
    // access_token 過期時間
    if (wx.getStorageSync('access_token') && expiration > timestamp) {
      console.log(wx.getStorageSync('access_token'))
      that.accessToken(wx.getStorageSync('access_token'))
    } else {
      wx.request({
        url: 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=appid&secret=secret',
        method: 'get',
        success: function (ress) {
          wx.setStorageSync("access_token", ress.data.access_token)
          var timestamp = Date.parse(new Date());
          var expiration = timestamp + ress.data.expires_in
          console.log(ress.data.access_token)
          wx.setStorageSync("expires_in", expiration)
          that.accessToken(ress.data.access_token)
        },
        fail: function (res) {
          console.log(res)
        }

      })
    }


  },
  accessToken(access_token) {
    let that = this
 
    let winWidth = wx.getSystemInfoSync().windowWidth; // 獲取當前設備的可視寬度
    let winHeight = wx.getSystemInfoSync().windowHeight; // 獲取當前設備的可視高度
    that.setData({
      winWidth: winWidth,
      winHeight: winHeight
    })
    let data = {
      page: 'pages/hotinfo/hotinfo',
      scene: '12'
    }
    wx.request({
      url: 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' + access_token,
      method: 'POST',
      data: data,
      // dataType: 'json',
      responseType: 'arraybuffer', //將返回數據 按文本解析修改為arraybuffer
      success: function (res) {
        console.log(res)
        
        // 利用writeFile bese64圖片存本地文件使用
        var imgPath = wx.env.USER_DATA_PATH + '/tabhome' + 'ewm' + '.png';
        var fs = wx.getFileSystemManager();
        fs.writeFileSync(imgPath, res.data, "base64");
   
          const ctx = wx.createCanvasContext('shareImg')
          var Rpx = (winWidth / 375).toFixed(2);
         
          ctx.setFillStyle('#fff')
          ctx.fillRect(0, 0, winWidth, 800)

          ctx.drawImage('../../' + res[0].path, 0, 0, winWidth, 228 * Rpx)

          var currentLineHeight = 228 * Rpx + 10;
          ctx.setTextAlign('left')
          ctx.setFillStyle('#2E2F2F')
          ctx.setTextAlign('left')
          let contentTitle = '世界之大無奇不有,只有不斷努力划水才能實現更加有珍貴的,你想要渾渾噩噩的日子,日子才會渾渾噩噩的對待你'
          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--; 
              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;
          }
          ctx.font = 'normal bold 18px sans-serif';
          for (var b = 0; b < row.length; b++) {
            currentLineHeight += Rpx * 30;
            ctx.fillText(row[b], 15, currentLineHeight);
          }
          currentLineHeight += 80 * Rpx
          ctx.drawImage('../../' + 'assets/coupon_gold.png', 20, currentLineHeight, 60 * Rpx, 60 * Rpx)
          currentLineHeight += 35 * Rpx
          ctx.fillText('健健康康', 90 * Rpx, currentLineHeight);
          ctx.drawImage(imgPath, winWidth - 120 * Rpx, currentLineHeight - 70, 100 * Rpx, 100 * Rpx)
          currentLineHeight += 100 - 40 * Rpx
          ctx.stroke()
          ctx.draw()
          that.setData({
            currentLineHeight: currentLineHeight
          })
        })
      }

  },
  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,
      destHeight: this.data.currentLineHeight,
      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.showLoading({
      title: '努力生成中...'
    })
    wx.canvasToTempFilePath({
      x: 0,
      y: 0,
      width: that.data.winWidth,
      height: that.data.winHeight - 70,
      destWidth: that.data.winWidth,
      destHeight: that.data.winHeight - 70,
      canvasId: 'shareImg',
      success: function (res) {
        console.log(res)
        wx.hideLoading()
        wx.saveImageToPhotosAlbum({
          filePath: res.tempFilePath,
          success(res) {
            wx.showModal({
              content: '圖片已保存到相冊',
              showCancel: false,
              confirmText: '知道啦',
              confirmColor: '#72B9C3',
              success: function (res) {
                if (res.confirm) {
                  console.log('用戶點擊確定');
                  that.setData({
                    hidden: true
                  })
                }
              }
            })
          }
        })
      },
      fail: function (res) {
        console.log(res)
      }
    })
  },
})

(https://api.weixin.qq.com接口只能后端請求  不然上線后會出問題 我這邊只供體驗參考)

本地圖片路徑錯誤繪制會失敗

1.通過小程序api 接口 https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=appid&secret=secret  (get)

獲取 token值  時效兩個小時 

2.再通過api 接口 https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=access_token 獲取自定義參數的小程序碼 (POST)

01.scene 為要攜帶的參數 最高32位   具體看小程序api文檔  接口返回的格式為 arraybuffer

02.請求是注意  參數修改  responseType: 'arraybuffer', //將返回數據 按文本解析修改為arraybuffer

03.通過api wx.arrayBufferToBase64() 將數據轉為bese64   例:

let URL ='data:image/png;base64,' + wx.arrayBufferToBase64(res.data)

04.小程序canvas bese64圖片 模擬器可正常顯示 真機操作則無效  因canvas圖片不支持base64 

處理方法為利用writeFile bese64圖片存本地文件使用 例:

var imgPath = wx.env.USER_DATA_PATH + '/tabhome' + 'ewm' + '.png';

var fs = wx.getFileSystemManager();

fs.writeFileSync(imgPath, res.data, "base64");

wx.env.USER_DATA_PATH 為微信提供無需在意   '/tabhome' 為本頁面路徑 ewm為自定義

writeFileSync內的imgPath為自定義的文件路徑 (本地路徑) 

writeFileSync內的res.data 為獲取到的arraybuffer值 

writeFileSync內的base64 為數據類型

imgPath拿到的 就是本地的圖片路徑 可直接使用到項目中

3.利用wx.createCanvasContext創建畫板 進行繪畫 文字太多 自動換行兩行省略處理 圖片路徑一定要正確 不然只會看到空白的canvas

4.利用wx.canvasToTempFilePath() 將canvas截取生成圖片  區域可自定義 具體請看官方文檔

5.wx.saveImageToPhotosAlbum  保存圖片到手機相冊

6.注意canvas圖片如果是網絡圖片 要通過 getImageInfo / downloadFile 先下載再使用

流程:

通過canvas提前繪制海報

再通過wx.canvasToTempFilePath() 截取繪制好的海報

最后通過wx.saveImageToPhotosAlbum  保存圖片到手機相冊

這樣就大功告成了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM