小程序生成海报遇见的坑

2019-04-21  本文已影响0人  wyc0859

生成海报,涉及小程序二维码生成,多图片合成,图片定位居中,多行文字,文字居中,禁止滚动等问题

1、首先base64图片不能和canvas合成
2、url图片必须用wx.downloadFile()先下载,返回结果为http://tmp/wx0b6251f....是正确结果
3、小程序二维码是在API服务器端生成的,点击

33.png
//解决禁止滚动问题
<!-- catchtouchmove="preventTouchMove" -->
<!--  disable-scroll="true" bindtouchstart="touchStart" -->
 <!--  disable-scroll="true" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd" -->

<view class='haibao' wx-if="{{haib}}" catchtouchmove="preventTouchMove">
  <view class='hb'>
    <view class='hb_01' bindtap='close_hb' hidden="{{btn_save}}">
      <image src='/imgs/xc.png'></image>
    </view>
    <view class='hb_02 poste_box' id='canvas-container'>
      <canvas canvas-id="myCanvas" style="width:100%;height:420px;" disable-scroll="true" bindtouchstart="touchStart"  />
      <!-- bindtouchmove="touchMove" bindtouchend="touchEnd" -->
    </view>
    <view class='hb_03' hidden="{{btn_save}}">
      <van-button round type="danger" bindtap="save"> 保存到本地</van-button>
    </view>
  </view>
  <v-black></v-black>
</view>
import {  HB } from '../../util/hb.js';
//显示海报框,并开始生成海报
  show_hb() {
    const that = this
    this.setData({
      haib: true,
      share_t: false,
      btn_save: false,
    })
    const obj = {
      id: 2,
      imgs: https://www.phps.shop/1.jpg,
      name: 'aaa',
      price: 1,
      market_price: 2,
    }
    HaoBao.create_hb(obj);
  },

//保存海报
  save() {
    const that=this
    HaoBao.save(res=>{ 
      if(res==1){
        that.setData({
          haib: false,
          share_t: false,
          btn_save: true,
        })
      }else{
        wx.showToast({
          title: '保存失败'
        })
      } 
    }) 
  } 

封装好的海报类

import {
  HTTP
} from 'http.js';
const http = new HTTP
class HB {
  cardInfo = {
    Company: '-- 如花商城 --',
    bgimg: 'https://wy.phps.shop/hb_bg.png',  //背景图
    wximg: 'https://wy.phps.shop/wx.png', //固定二维码
    goodsimg: '',
    Name: '', 
    Price: '',
    market_price: '',
    id:''
  } 
  create_hb(obj){ 
    obj.imgs = obj.imgs.replace('http://', 'https://');
    this.cardInfo.Name=obj.name
    this.cardInfo.Price = '¥ '+obj.price
    this.cardInfo.market_price = '原价 '+obj.market_price
    this.cardInfo.goodsimg = obj.imgs
    this.cardInfo.goods_id = obj.id  
    this.get_codeimg()
  }

  //获取小程序码
  get_codeimg() { 
    const that = this
    const id = that.cardInfo.id
    //that.getQrCode(that.cardInfo.wximg) //使用固定二维码
    /*  动态获取二维码  */
    http.request({
      url: '/get_codeimg',
      data: {
        path: 'pages/goods/index?id=' + id
      }
    }).then(res => {
      that.getQrCode(res)
    })
  }

  //下载二维码图片,虽然已经有二维码图片了,但必须wx.downloadFile后才能绘制
  getQrCode(urls) {
    var that = this;
    console.log('二维码0', urls)
    wx.showLoading({
      title: '生成中...',
      mask: true,
    })
    wx.downloadFile({
      url: urls, //二维码路径
      success: function (res) {
        wx.hideLoading();
        if (res.statusCode === 200) {
          var codeSrc = res.tempFilePath;
          console.log('二维码1', res)
          that.down_bg(codeSrc);
        } else {
          wx.showToast({
            title: '二维码下载失败!',
            icon: 'none',
            duration: 2000,
            success: function () {
              var codeSrc = "";
              that.down_bg(codeSrc);
            }
          })
        }
      }
    })
  }

  //下载背景图
  down_bg(urls) {
    var that = this;
    wx.showLoading({
      title: '生成中...',
      mask: true,
    })
    console.log('bgimg:', that.cardInfo.bgimg)
    wx.downloadFile({
      url: that.cardInfo.bgimg,
      success: function(res) {
        console.log('bgcode:', res.tempFilePath)
        wx.hideLoading();
        if (res.statusCode === 200) {
          var bg = res.tempFilePath;
          that.getAvaterInfo(bg, urls);
        } else {
          wx.showToast({
            title: '商品图片下载失败!',
            icon: 'none',
            duration: 2000,
            success: function() {
              var bg = "";
              that.getAvaterInfo(bg, urls);
            }
          })
        }
      }
    })
  }

  //下载商品图片
  getAvaterInfo(bg, urls) {
    var that = this; 
    wx.showLoading({
      title: '生成中...',
      mask: true,
    }) 
    wx.downloadFile({
      url: that.cardInfo.goodsimg, //图片路径
      success: function(res) {
        console.log('goodsimg:', res.tempFilePath)
        wx.hideLoading();
        if (res.statusCode === 200) {
          var avaterSrc = res.tempFilePath; //下载成功返回结果
          that.sharePosteCanvas(bg, urls, avaterSrc); //生成海报
        } else {
          wx.showToast({
            title: '商品图片下载失败!',
            icon: 'none',
            duration: 2000,
            success: function() {
              var avaterSrc = "";
              that.sharePosteCanvas(bg, urls, avaterSrc); 
            }
          })
        }
      }
    })
  }
  
  //绘制海报
  sharePosteCanvas(bj, codeSrc, avaterSrc) {
    wx.showLoading({
      title: '生成中...',
      mask: true,
    })
    let {
      windowWidth
    } = wx.getSystemInfoSync();
    windowWidth = windowWidth * 0.72 //css中设置的是72%宽
    console.log('w:', windowWidth)
    var that = this;
    var cardInfo = that.cardInfo; //需要绘制的数据集合
    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 = 15;
      ctx.setFillStyle('#fff');
      ctx.fillRect(0, 0, rect.width, height);

      //背景图片
      if (bj) {
        ctx.drawImage(bj, 0, 0, windowWidth, 420);
        ctx.setFontSize(14);
        ctx.setFillStyle('#fff');
        ctx.setTextAlign('left');
      }
      //公司名称 
      if (cardInfo.Company) {
        ctx.setFontSize(14);
        ctx.setFillStyle('#333');
        ctx.setTextAlign('center');
        let fw = ctx.measureText(cardInfo.Company) //计算文字总宽度,ctx.setTextAlign('leftr')时有用
        ctx.fillText(cardInfo.Company, windowWidth / 2, 25);  /*参数为:图片,左,上*/
      }

      // //商品图片
      if (avaterSrc) {
        ctx.drawImage(avaterSrc, left, 35, width + 25, 180);  //参数为:图片,左,上,宽,高
        ctx.setFontSize(14);
        ctx.setFillStyle('#fff');
        ctx.setTextAlign('left');
      }

      //商品名称
      if (cardInfo.Name) {
        const CONTENT_ROW_LENGTH = 32; // 正文 单行显示字符长度
        let [contentLeng, contentArray, contentRows] = that.textByteLength(cardInfo.Name, CONTENT_ROW_LENGTH);

        ctx.setFontSize(14);
        ctx.setFillStyle('#000');
        if (contentLeng < 33) {
          ctx.setTextAlign('center');
          ctx.fillText(cardInfo.Name, windowWidth / 2, width + 33);
        } else {
          ctx.setTextAlign('left');
          let contentHh = 22 * 1;
          for (let m = 0; m < contentArray.length; m++) {
            ctx.fillText(contentArray[m], left + 10, width + 33 + contentHh * m);
          }
        }
      }

      //商品价格
      if (cardInfo.Price) {
        ctx.setFontSize(16);
        ctx.setTextAlign('center');
        ctx.setFillStyle("#FF4444")
        var price_width = ctx.measureText(cardInfo.Price)
        ctx.fillText(cardInfo.Price, (windowWidth - price_width.width) / 2, width + 82);
      }

      //商品原价
      if (cardInfo.market_price) {
        ctx.setFontSize(12);
        ctx.setTextAlign('center');
        ctx.setFillStyle("#666")
        ctx.fillText(cardInfo.market_price, (windowWidth + price_width.width) / 2 + 10, width + 82);
      }


      ctx.setFontSize(14);
      ctx.setFillStyle('#000');
      ctx.setTextAlign('left');
      ctx.fillText('长按识别小程序二维码', left + 90, width + 150);

      ctx.setFontSize(12);
      ctx.setFillStyle('#666');
      ctx.setTextAlign('left');
      ctx.fillText('好货要和朋友一起分享', left + 90, width + 180);
      
      //  绘制二维码
      if (codeSrc) {
        ctx.drawImage(codeSrc, left, width + 125, width / 3, width / 3)
      }

    }).exec()

    setTimeout(function() {
      ctx.draw();
      wx.hideLoading();
    }, 1000)
  }

  //多行文字换行
  textByteLength(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] //  [处理文字的总字节长度,每行显示内容的数组,行数]
  }

  //点击保存到相册
  save(callback) {
    var that = this;
    wx.showLoading({
      title: '正在保存',
      mask: true,
    })
    wx.canvasToTempFilePath({
      canvasId: 'myCanvas',
      success: function(res) {
        wx.hideLoading();
        var tempFilePath = res.tempFilePath;
        wx.getSetting({
          success(res) {
            if (!res.authSetting['scope.writePhotosAlbum']) {
              wx.authorize({
                scope: 'scope.writePhotosAlbum',
                success() {
                  that.save_phones(tempFilePath, callback)
                }
              })
            } else {
              that.save_phones(tempFilePath, callback)
            }
          }
        })
      }
    });
  }

  save_phones(tempFilePath, callback) {
    wx.saveImageToPhotosAlbum({
      filePath: tempFilePath,
      success(res) {
        wx.showModal({
          content: '图片已保存到相册,赶紧晒一下吧',
          showCancel: false,
          confirmText: '好的',
          confirmColor: '#333',
          success: function(res) {
            callback(1)
          },
          fail: function(res) {
            callback(0)
          }
        })
      },
      fail: function(res) {
        wx.showToast({
          title: res.errMsg,
          icon: 'none',
          duration: 2000
        })
        callback(0)
      }
    })
  }
}
export {  HB};

遇到的错误提示

1、错误码:48001 api unauthorized hint:
AccessToken错误或过期
2、

上一篇下一篇

猜你喜欢

热点阅读