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

项目中遇到需要分享到朋友圈,但是查询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
      })
    });
   
  },

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

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

上一篇:小程序使用npm


下一篇:调用微信退款接口时出现System.Security.Cryptography.CryptographicException: 出现了内部错误 解决办法