微信小程序之生成海报并保存到本地

Posted on 2019-09-23 12:08  jessie-xian  阅读(3236)  评论(0编辑  收藏  举报

项目中遇到需要分享到朋友圈,但是查询api发现小程序并没有提供分享到朋友圈的功能,只能实现通过canvas画一张海报然后保存到本地,让用户主动去发朋友圈。
效果图生成后海报
首先使用微信小程序提供的canvasapi将第二张图显示的海报画出来
然后调用保存本地的接口
wx.saveImageToPhotosAlbum({})将图片保存在本地相册中

wxml部分
 <view hidden='{{maskFlag==false}}'>
        <view class='mask'></view>
        <view class='shareWay'>
          <view class='selectWay'>
            <button class='weixin' open-type="share">
              <view class='wechatImg'>
                <image class='wechatIcon' src='../../images/wechat.png'></image>
              </view>
              <view class='sentFriend'>发送给好友</view>
            </button>
            <view class='middleLine'></view>
            <view class='haibao' bindtap='formSubmit'>
              <view class='posterImg'>
                <image class='posterIcon' src='../../images/haibao.png'></image>
              </view>
              <view class='createPoster'>生成海报</view>
            </view>
            <!--生成海报  -->
            <view class='imagePathBox' hidden="{{maskHidden == false}}">
              <view class='poster'>
                <image src="{{imagePath}}" class='shengcheng'></image>
              </view>
              <button class='baocun' bindtap='savePoster'>保存图片</button>
            </view>

            <view class="canvas-box">
              <canvas style="width: 375px;height: 667px;position:fixed;top:9999px" canvas-id="mycanvas" />
            </view>
          </view>
          <view class='shareEmpty'></view>
          <view class='cancel' bindtap='cancelShare'>取消</view>
        </view>
      </view>
wxss部分
.mask {
  width: 100%;
  height: 100%;
  position: absolute;
  background-color: rgb(0, 0, 0);
  z-index: 1000;
  top: 0;
  left: 0;
  opacity: 0.5;
}

.shareWay {
  width: 750rpx;
  height: 372rpx;
  border-radius: 10rpx 10rpx 0 0;
  /* margin-bottom: 114rpx; */
  position: fixed;
  bottom: 0;
  z-index: 9999;
  background-color: #fff;
}

.selectWay {
  display: flex;
  width: 100%;
  height: 250rpx;
  justify-content: space-between;
}

.middleLine {
  /* width: 1rpx; */
  height: 80rpx;
  background: rgba(216, 216, 216, 1);
  opacity: 0.3;
  border: 1rpx solid rgba(151, 151, 151, 1);
  margin: 68rpx auto 0;
}

.weixin {
  width: 48%;
  background-color: #fff;
}

.wechatImg, .posterImg {
  width: 88rpx;
  height: 88rpx;
  margin: 53rpx auto 0;
}

.wechatIcon, .posterIcon {
  width: 100%;
  height: 100%;
  display: block;
}

.sentFriend, .createPoster {
  width: 100%;
  height: 40rpx;
  font-size: 28rpx;
  font-family: PingFangSC-Regular;
  font-weight: 400;
  color: rgba(51, 51, 51, 1);
  line-height: 40rpx;
  text-align: center;
  margin-top: 24rpx;
}

.haibao {
  width: 48%;
}

.shareEmpty {
  width: 750rpx;
  height: 14rpx;
  background: rgba(245, 247, 250, 1);
}

.cancel {
  width: 100%;
  height: 108rpx;
  font-size: 32rpx;
  font-family: PingFangSC-Regular;
  font-weight: 400;
  color: rgba(51, 51, 51, 1);
  line-height: 108rpx;
  text-align: center;
}

.imagePathBox {
  width: 100%;
  height: 100%;
  background: rgba(255, 255, 255, 1);
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  border-top: 2rpx solid rgba(183, 183, 183, 0.2);
  z-index: 10;
}

.poster {
  width: 670rpx;
  height: 959rpx;
  background: rgba(255, 255, 255, 1);
  position: fixed;
  left: 40rpx;
  top: 43rpx;
  right: 0;
  bottom: 0;
  border-top: 2rpx solid rgba(183, 183, 183, 0.2);
  /* box-shadow: 0px -10px 14px 0px rgba(183,183,183,0.2); */
  z-index: 10;
}

.shengcheng {
  width: 670rpx;
  height: 959rpx;
  border-radius: 12rpx;
  position: fixed;
  left: 40rpx;
  top: 43rpx;
  box-sizing: border-box;
  background-color: #fff;
  z-index: 10;
  box-shadow: 0px 10px 14px 0px rgba(194, 194, 194, 0.5);
  /* padding: 23rpx 21rpx 36rpx; */
}

.baocun {
  width: 670rpx;
  height: 88rpx;
  background: linear-gradient(90deg, rgba(255, 114, 126, 1) 0%, rgba(239, 69, 85, 1) 100%);
  box-shadow: 0px 4px 8px 0px rgba(244, 82, 98, 0.45);
  border-radius: 8rpx;
  display: block;
  padding: 0;
  line-height: 80rpx;
  text-align: center;
  position: fixed;
  bottom: 40rpx;
  left: 40rpx;
  color: #fff;
  font-size: 32rpx;
}

button[class="baocun"]::after {
  border: 0;
}

.cancelFocus {
  width: 308rpx;
  height: 114rpx;
  text-align: center;
  font-size: 32rpx;
  font-family: PingFangSC-Regular;
  font-weight: 400;
  line-height: 114rpx;
  color: #999;
}

.qrcode {
  width: 278rpx;
  height: 278rpx;
  display: block;
  margin: 0 auto;
}
js部分
// 生成海报并分享给好友
  //将canvas转换为图片保存到本地,然后将图片路径传给image图片的src
  createNewImg: function() {
    var that = this;
    // console.log(that.data.qrcode)
    var context = wx.createCanvasContext('mycanvas');
    context.setFillStyle("#ffffff")
    context.fillRect(0, 0, 670, 959)
    var path = that.data.MainImages;
    //将模板图片绘制到canvas,在开发工具中drawImage()函数有问题,不显示图片
    context.drawImage(path, 16, 14, 344, 425);
    var path1 = that.data.brandImg;
    //将模板图片绘制到canvas,在开发工具中drawImage()函数有问题,不显示图片
    var path2 = "/images/middle.png";
    var path3 = that.data.brandImg;
    // var path3 = '../../images/poster.png';
    var path4 = that.data.qrcode;
    var path5 = "/images/zhiwen.png";
    //不知道是什么原因,手机环境能正常显示
    context.save(); // 保存当前context的状态

    //绘制品牌头像
    context.drawImage(path3, 20, 507, 70, 80);
    //绘制商品对应的品牌名称
    context.setFontSize(18);
    context.setFillStyle('#000000');
    context.setTextAlign('left');
    context.fillText(that.data.Name, 92, 525);
    context.stroke();
    //绘制扫码即可查看商品更多信息
    context.drawImage(path4, 245, 500, 115, 125); //二维码
    context.setFontSize(14);
    context.setFillStyle('#A0A0A0');
    context.setTextAlign('left');
    context.fillText(that.data.scan, 65, 618);
    context.stroke();
    //绘制商品
    context.drawImage(path5, 25, 600, 26, 24);
    context.stroke();
    context.setFontSize(18);
    context.setFillStyle('#000000');
    context.setTextAlign('left');
    context.fillText(that.data.goodsObj.Name, 92, 570);
    context.stroke();
    //绘制中间分割线
    context.drawImage(path2, -8, 455, 390, 45);
    context.draw(true, setTimeout(function() {
      //将生成好的图片保存到本地,需要延迟一会,绘制期间耗时
      wx.canvasToTempFilePath({
        x: 0,
        y: 0,
        width: 670,
        height: 959,
        destWidth: 2010,
        destHeight: 2877,
        canvasId: 'mycanvas',
        success: function(res) {
          var tempFilePath = res.tempFilePath;
          that.setData({
            imagePath: tempFilePath,
            canvasHidden: true
          });
        },
        fail: function(res) {
          console.log(res);
        }
      });
    }, 200));
  },

  //点击保存到相册
  savePoster: function() {
    var that = this
    console.log(that.data.imagePath)
    wx.saveImageToPhotosAlbum({
      filePath: that.data.imagePath,
      success(res) {
        wx.showModal({
          content: '海报已保存到相册',
          showCancel: false,
          confirmText: '好的',
          confirmColor: '#333',
          success: function(res) {
            if (res.confirm) {
              console.log('999999')
              console.log('用户点击确定');
              /* 该隐藏的隐藏 */
              that.setData({
                maskHidden: false
              })
            }
          },
          fail: function(res) {
            console.log(11111)
          }
        })
      },
      fail(res) {
        // wx.showToast({
        //   title: '保存失败',
        //   icon: 'none',
        // })
        if (res.errMsg === "saveImageToPhotosAlbum:fail:auth denied" || res.errMsg === "saveImageToPhotosAlbum:fail auth deny") {
          // 这边微信做过调整,必须要在按钮中触发,因此需要在弹框回调中进行调用
          wx.showModal({
            title: '提示',
            content: '需要您授权保存相册',
            showCancel: false,
            success: modalSuccess => {
              wx.openSetting({
                success(settingdata) {
                  console.log("settingdata", settingdata)
                  if (settingdata.authSetting['scope.writePhotosAlbum']) {
                    wx.showModal({
                      title: '提示',
                      content: '获取权限成功,再次点击图片即可保存',
                      showCancel: false,
                    })
                  } else {
                    wx.showModal({
                      title: '提示',
                      content: '获取权限失败,将无法保存到相册哦~',
                      showCancel: false,
                    })
                  }
                },
                fail(failData) {
                  console.log("failData", failData)
                },
                complete(finishData) {
                  console.log("finishData", finishData)
                }
              })
            }

          })
        }
      }
    })
  },
  //点击生成
  formSubmit: function(e) {

    var that = this;
    this.setData({
      maskHidden: false
    });
    wx.showToast({
      title: '海报生成中...',
      icon: 'loading',
      duration: 1000
    });
    setTimeout(function() {
      wx.hideToast()
      that.createNewImg();
      that.setData({
        maskHidden: true
      });
    }, 1000)
  },

  //适配不同屏幕大小的canvas
  getQRCodeSize: function() {
    var size = 0;
    try {
      var res = wx.getSystemInfoSync();
      var scale = 750 / 278; //不同屏幕下QRcode的适配比例;设计稿是750宽
      var width = res.windowWidth / scale;
      size = width;

    } catch (e) {
      // Do something when catch error
      // console.log("获取设备信息失败"+e);
    }
    return size;
  },
  createQRCode: function(text, size) {
    //调用插件中的draw方法,绘制二维码图片

    let that = this

    // console.log('QRcode: ', text, size)
    let _img = QR.createQrCodeImg(text, {
      size: parseInt(size)
    })
    // let qucode = that.data.qucode;
    // qucode=_img
    that.setData({
      'qrcode': _img
    })
    console.log('商品二维码----->', that.data.qrcode,that.data.qrcode.length)    
    
    // 处理二维码成本地图片
   
    base64src(that.data.qrcode, res => {
      console.log(res) // 返回图片地址,直接赋值到image标签即可
      that.setData({
        'qrcode': res
      })
    });
   
  },

(二维码的处理见下一篇)