美文网首页前端
小程序如何生成图片保存到相册

小程序如何生成图片保存到相册

作者: MrHong_bfea | 来源:发表于2020-08-30 21:49 被阅读0次

首先我们先来看看生成的图片


微信图片_20200830213420.png

废话就不多说了,我们来看看代码的实现吧

<canvas style="width:100%;height:{{contentHeight}}px" canvas-id="myCanvas"></canvas>
data: {
   // canvas
    windowWidth: 0, //屏幕宽度
    windowHeight: 0, //屏幕高度
    contentHeight: 0, //内容高度
    canvasUrl: '', //canvas李彪
    qrCode:
      'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1254162229,4079702590&fm=26&gp=0.jpg', //小程序码https图片路径
    shopImg:
      'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1254162229,4079702590&fm=26&gp=0.jpg', //商品图片
    sharePopup: false, //显示分享弹窗
    goodsInfoImg: '', //转换临时图片的商品图片
    canvasTempFile: '' //canvas临时图片
}
 /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    var that = this
    that.setData({
      insideWidth: '100%'
    })
    //获取设备信息高度。计算出其他的高度等
    wx.getSystemInfo({
      success: function(res) {
        that.setData({
          windowWidth: res.windowWidth,
          windowHeight: res.windowHeight,
          boxWidth: res.windowWidth * 0.75, //分享图片box宽度
          boxheight: res.windowWidth * (0.222 + 0.72 + 0.192) + 90, //分享图片box高度
          boxPageY: res.windowWidth * 0.081, //boxY轴位置
          shadowWidth: res.windowWidth * 0.6, //阴影宽度
          shadowHeight: res.windowWidth * 0.78, //阴影高度
          imgPageY: res.windowWidth * 0.232 //商品图片Y轴位置
          // codeWidth: res.windowWidth * 0.192, //小程序码图片宽度
          // codeHeight: res.windowWidth * 0.192, //小程序码图片高度
        })
      }
    })
    //网络图片转为本地图片,直接显示网络图片的话真机不显示
    that.getTempFile(that.data.shopImg)
  },

  //drawImage绘制的图片需要通过getImageInfo/downloadFile获取商品临时图片路径
  getTempFile: function(url) {
    wx.showLoading({
      title: '图片生成中'
    })
    let that = this
    wx.downloadFile({
      url: url,
      success: function(res) {
        that.setData({
          goodsInfoImg: res.tempFilePath
        })
        //继续生成商品的小程序码
        that.downloadSkuQrCode(that.data.qrCode)
      },
      fail: function(err) {
        wx.showToast({
          title: '下载商品图片失败,稍后重试!',
          icon: 'none',
          duration: 5000
        })
      }
    })
  },

  getData() {
    let that = this
    wx.getImageInfo({
      src: that.data.shopImg,
      success(res) {
        var imgsize = that.getimageSize(
          { width: res.width, height: res.height },
          that.data.shadowWidth,
          95
        )
        that.setData({
          imgWidth: imgsize.width,
          imgHeight: imgsize.height
        })
        that.createNewImg()
      }
    })
  },

  // 图片适配(aspectFill)
  getimageSize: function(imageSize, w, h) {
    if (imageSize.width < w) {
      if (imageSize.height < h) {
        var scale1 = imageSize.height / imageSize.width
        var scale2 = h / imageSize.height
        if (scale1 > scale2) {
          imageSize.height = (imageSize.height / imageSize.width) * w
          imageSize.width = w
        } else {
          imageSize.width = (imageSize.width / imageSize.height) * h
          imageSize.height = h
        }
      } else {
        imageSize.height = (imageSize.height / imageSize.width) * w
        imageSize.width = w
      }
    } else if (imageSize.height < h) {
      if (imageSize.width < w) {
        var scale1 = imageSize.height / imageSize.width
        var scale2 = h / imageSize.height
        if (scale1 > scale2) {
          imageSize.height = (imageSize.height / imageSize.width) * w
          imageSize.width = w
        } else {
          imageSize.width = (imageSize.width / imageSize.height) * h
          imageSize.height = h
        }
      } else {
        imageSize.width = (imageSize.width / imageSize.height) * h
        imageSize.height = h
      }
    } else {
      var scale1 = imageSize.height / imageSize.width
      var scale2 = h / imageSize.height
      if (scale1 > scale2) {
        imageSize.height = (imageSize.height / imageSize.width) * w
        imageSize.width = w
      } else {
        imageSize.width = (imageSize.width / imageSize.height) * h
        imageSize.height = h
      }
    }
    return imageSize
  },

  //画矩形,也是整块画布的大小,宽度是屏幕宽度,高度根据内容多少来动态设置。
  drawSquare: function(ctx, height, color) {
    let that = this
    // 绘制大长方矩形
    ctx.setFillStyle(color)
    ctx.fillRect(
      (that.data.windowWidth - that.data.boxWidth) / 2,
      that.data.boxPageY,
      that.data.boxWidth,
      height
    )
    // // 绘制中间块矩形
    // ctx.setFillStyle('red')
    // ctx.fillRect(
    //   (that.data.windowWidth-that.data.shadowWidth)/2,
    //   that.data.imgPageY,
    //   that.data.shadowWidth,
    //   that.data.shadowWidth
    // )
  },

  // ctx:canvas中的createCanvasContext,
  // x:矩形左上角的x坐标
  // y:矩形左上角的y坐标
  // w:矩形宽度
  // h:矩形高度
  // r:圆弧半径
  roundRect: function(ctx, x, y, w, h, r) {
    // 开始绘制
    ctx.beginPath()
    // 因为边缘描边存在锯齿,最好指定使用 transparent 填充
    // 这里是使用 fill 还是 stroke都可以,二选一即可
    ctx.setFillStyle('transparent')
    // ctx.setStrokeStyle('transparent')
    // 左上角
    ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)

    // border-top
    ctx.moveTo(x + r, y)
    ctx.lineTo(x + w - r, y)
    ctx.lineTo(x + w, y + r)
    // 右上角
    ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)

    // border-right
    ctx.lineTo(x + w, y + h - r)
    ctx.lineTo(x + w - r, y + h)
    // 右下角
    ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)

    // border-bottom
    ctx.lineTo(x + r, y + h)
    ctx.lineTo(x, y + h - r)
    // 左下角
    ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)

    // border-left
    ctx.lineTo(x, y + r)
    ctx.lineTo(x + r, y)

    // 这里是使用 fill 还是 stroke都可以,二选一即可,但是需要与上面对应
    ctx.fill()
    // ctx.stroke()
    ctx.closePath()
    // 剪切
    ctx.clip()
    ctx.restore()
  },

  // 根据文字多少动态计算高度,然后依次画出矩形,文字,横线和小程序码。
  createNewImg: function() {
    let that = this
    let ctx = wx.createCanvasContext('myCanvas')
    // let contentHeight = that.data.boxheight  //修改图片高度
    let contentHeight = that.data.shadowWidth + that.data.imgPageY + 100
    // 绘制圆角矩形
    that.roundRect(
      ctx,
      (that.data.windowWidth - that.data.boxWidth) / 2,
      that.data.boxPageY,
      that.data.boxWidth,
      contentHeight - 32,
      14
    )
    that.drawSquare(ctx, contentHeight, '#333')
    that.setData({
      contentHeight: contentHeight
    })
    //商品图片
    // 绘制图片圆角
    let bg_r = 14
    ctx.save()
    ctx.beginPath()
    ctx.arc(
      (that.data.windowWidth - that.data.imgWidth) / 2 + bg_r,
      that.data.imgPageY + bg_r,
      bg_r,
      Math.PI,
      Math.PI * 1.5
    )
    ctx.arc(
      (that.data.windowWidth - that.data.imgWidth) / 2 +
        that.data.imgWidth -
        bg_r,
      that.data.imgPageY + bg_r,
      bg_r,
      Math.PI * 1.5,
      Math.PI * 2
    )
    ctx.arc(
      (that.data.windowWidth - that.data.imgWidth) / 2 +
        that.data.imgWidth -
        bg_r,
      that.data.imgPageY + that.data.imgHeight - bg_r,
      bg_r,
      0,
      Math.PI * 0.5
    )
    ctx.arc(
      (that.data.windowWidth - that.data.imgWidth) / 2 + bg_r,
      that.data.imgPageY + that.data.imgHeight - bg_r,
      bg_r,
      Math.PI * 0.5,
      Math.PI
    )
    ctx.clip()
    ctx.drawImage(
      that.data.goodsInfoImg,
      (that.data.windowWidth - that.data.imgWidth) / 2,
      that.data.imgPageY,
      that.data.imgWidth,
      that.data.imgHeight
    )
    ctx.restore()
    // 绘制商品蒙层矩形
    ctx.save()
    ctx.beginPath()
    ctx.arc(
      (that.data.windowWidth - that.data.imgWidth) / 2 + bg_r,
      that.data.imgPageY + that.data.imgHeight - 60 + bg_r,
      30,
      Math.PI,
      Math.PI * 1.5
    )
    ctx.arc(
      (that.data.windowWidth - that.data.imgWidth) / 2 +
        that.data.imgWidth -
        bg_r,
      that.data.imgPageY + that.data.imgHeight - 60 + bg_r,
      30,
      Math.PI * 1.5,
      Math.PI * 2
    )
    ctx.arc(
      (that.data.windowWidth - that.data.imgWidth) / 2 +
        that.data.imgWidth -
        bg_r,
      that.data.imgPageY + that.data.imgHeight - 60 + 60 - bg_r,
      bg_r,
      0,
      Math.PI * 0.5
    )
    ctx.arc(
      (that.data.windowWidth - that.data.imgWidth) / 2 + bg_r,
      that.data.imgPageY + that.data.imgHeight - 60 + 60 - bg_r,
      bg_r,
      Math.PI * 0.5,
      Math.PI
    )
    ctx.clip()
    ctx.setFillStyle('rgba(0,0,0,0.5)')
    ctx.fillRect(
      (that.data.windowWidth - that.data.imgWidth) / 2,
      that.data.imgPageY + that.data.imgHeight - 60,
      that.data.imgWidth,
      60
    )
    ctx.restore()
    ctx.setFillStyle('#fff')
    ctx.font = 'normal 13px Microsoft YaHei'
    ctx.fillText(
      '标题logo',
      (that.data.windowWidth - that.data.shadowWidth) / 2,
      that.data.imgPageY - 10
    )
    ctx.setFillStyle('#fff')
    // ctx.setTextAlign="center"
    ctx.fillText(
      '填商品名字',
      (that.data.windowWidth - ctx.measureText('填商品名字').width) * 0.5,
      that.data.imgPageY + that.data.imgHeight - 40
    )
    ctx.font = 'normal 22px Microsoft YaHei'
    ctx.setFillStyle('#ECC781')
    ctx.fillText(
      '填价格',
      (that.data.windowWidth - ctx.measureText('填价格').width) * 0.5,
      that.data.imgPageY + that.data.imgHeight - 10
    )
    // 绘制您的好友
    ctx.font = 'normal 16px Microsoft YaHei'
    ctx.setFillStyle('#fff')
    ctx.fillText(
      '您的好友已为您',
      (that.data.windowWidth - that.data.shadowWidth) / 2,
      that.data.shadowWidth + that.data.imgPageY + 30
    )
    ctx.font = 'normal 16px Microsoft YaHei'
    ctx.setFillStyle('#fff')
    ctx.fillText(
      '这里填所需文字',
      (that.data.windowWidth - that.data.shadowWidth) / 2,
      that.data.shadowWidth + that.data.imgPageY + 52
    )
    // 绘制长按识别小程序
    ctx.font = 'normal 12px Microsoft YaHei'
    ctx.setFillStyle('#AAAAAA')
    ctx.fillText(
      '长按识别小程序即可参与',
      (that.data.windowWidth - that.data.shadowWidth) / 2,
      that.data.shadowWidth + that.data.imgPageY + 80
    )
    // 填充小程序码
    ctx.drawImage(
      that.data.qrCode,
      (that.data.windowWidth - that.data.shadowWidth) / 2 +
        that.data.shadowWidth -
        that.data.codeWidth,
      that.data.shadowWidth + that.data.imgPageY + 80 - that.data.codeHeight,
      that.data.codeWidth,
      that.data.codeHeight
    )
    ctx.draw() //绘制到canvas
    that.generateCanvasImg()
  },

  //下载小程序码
  downloadSkuQrCode: function(url) {
    let that = this
    wx.downloadFile({
      url: url,
      success: function(res) {
        that.setData({
          qrCode: res.tempFilePath
        })
        //生成数据
        wx.getImageInfo({
          src:
            'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1254162229,4079702590&fm=26&gp=0.jpg',
          success(res) {
            that.setData({
              codeWidth: res.width * 0.1,
              codeHeight: res.height * 0.1
            })
            that.getData()
          }
        })
      },
      fail: function(err) {
        wx.showToast({
          title: '下载商品码失败,稍后重试!',
          icon: 'none',
          duration: 5000
        })
      }
    })
  },
// 生成图片中,这个方法是生成临时图片代替canvas展示,因为小程序里面canvas的层级太高,会挡住弹窗的内容,所有需要把canvas放到视图之外,用img展示即可
  generateCanvasImg() {
    var that = this
    setTimeout(function() {
      wx.canvasToTempFilePath({
        x: (that.data.windowWidth - that.data.boxWidth) / 2,
        y: that.data.boxPageY,
        width: that.data.boxWidth,
        height: that.data.shadowWidth + that.data.imgPageY + 68,
        destWidth: that.data.boxWidth * wx.getSystemInfoSync().pixelRatio,
        destHeight:
          (that.data.shadowWidth + that.data.imgPageY + 68) *
          wx.getSystemInfoSync().pixelRatio,
        canvasId: 'myCanvas',
        success: function(res) {
          wx.hideLoading()
          that.setData({
            canvasTempFile: res.tempFilePath
          })
        },
        fail: function(res) {}
      })
    }, 1000)
  },

//点击保存到相册前验证是否授权  最这两个方法就是保存相册了  把它放置到按钮的点击事件即可
  saveShareImg: function() {
    wx.getSetting({
      success: res => {
        if (!res.authSetting['scope.writePhotosAlbum']) {
          //未授权的话发起授权
          wx.authorize({
            scope: 'scope.writePhotosAlbum',
            success: () => {
              //用户允许授权,保存到相册
              this.saveImg()
            },
            fail: () => {
              //用户拒绝授权,然后就引导授权(这里的话如果用户拒绝,不会立马弹出引导授权界面,坑就是上边所说的官网原因)
              wx.showModal({
                content: '保存到相册需要获得你的授权',
                showCancel: false,
                confirmText: '确认',
                success: function(res) {
                  wx.openSetting({
                    success: () => {
                      wx.authorize({
                        scope: 'scope.writePhotosAlbum',
                        succes: () => {
                          //授权成功,保存图片
                          this.saveImg()
                        }
                      })
                    }
                  })
                },
                fail: function(res) {}
              })
            }
          })
        } else {
          //已经授权
          this.saveImg()
        }
      }
    })
  },

  saveImg() {
    var that = this
    wx.showLoading({
      title: '正在保存',
      mask: true
    })
    wx.saveImageToPhotosAlbum({
      filePath: that.data.canvasTempFile,
      success(res) {
        wx.hideLoading()
        wx.showModal({
          content: '图片已保存到相册,赶紧晒一下吧~',
          showCancel: false,
          confirmText: '好的',
          success: function(res) {
            if (res.confirm) {
            }
          },
          fail: function(res) {}
        })
        that.setData({
          sharePopup: false
        })
      },
      fail: function(res) {
        wx.showToast({
          title: '保存失败',
          icon: 'none',
          duration: 2000
        })
      }
    })
  },

相关文章

网友评论

    本文标题:小程序如何生成图片保存到相册

    本文链接:https://www.haomeiwen.com/subject/dltysktx.html