zoukankan      html  css  js  c++  java
  • 小程序 生成自定义小程序二维码码 通过 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="36rpx;" mode="widthFix"></image>
        <view class="share-title">分享</view>
      </button>
    </view>

    css

    
    .canvas-exp{
      100%;height:606px;background:#fff;
    }
    .preview {
       100%;
      height: 100%;
      background: rgba(0,0,0,1);
      position:fixed;
      top: 0;
      left: 0;
      z-index: 2;
    }
    .previewImg{
       88%;
      position: absolute;
      top: 100rpx;
      left: 6%;
      z-index: 3;
      border: 1px solid #000;
      border-radius: 5px;
      max-height: 800rpx;
    }
    .preview button{
       78%;
      position: absolute;
      top: 960rpx;
      left: 11%;
      border-radius: 2px;
    }
    .preview .cler{
       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{
       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,
           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,
           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  保存图片到手机相册

    这样就大功告成了

  • 相关阅读:
    可变长参数
    函数的参数
    函数
    文件操作
    字符编码
    数据类型的内置方法:集合
    数据类型的内置方法:元组
    数据类型的内置方法:字典
    数据类型内置方法:列表
    js对对象引用
  • 原文地址:https://www.cnblogs.com/wukongz/p/13064755.html
Copyright © 2011-2022 走看看