微信小程序实现九宫格切图,保存功能!

效果如下图:

 

代码如下:

<view class='sudoku'>
  <scroll-view scroll-x scroll-y class='canvas-box'>
    <canvas canvas-id='canvasIn' id='canvas' class='canvas canvas-in' style='{{canvasWH}}'></canvas>
    <!-- wx:if='{{canvasIn}}' -->
    <!-- <canvas canvas-id='canvasOut' id='canvasOut' class='canvas canvas-out' style='{{canvasWH}}'></canvas> -->
  </scroll-view>
  <cover-view class='imgs'>
    <cover-view class='imgs-box'>
      <cover-image class='img' data-idx='{{index+1}}' src='{{item}}' style='{{maxHeight}}' wx:for='{{imgUrls}}' wx:key='{{index}}' bindtap='saveImg'></cover-image>
    </cover-view>
  </cover-view>
  <cover-view class='btns-box'>
    <button bindtap='uploadImg' class='btn btn-cut'>上传</button>
    <button bindtap='saveAll' class='btn btn-save'>保存</button>
  </cover-view>
</view>
let _this
Page({

  /**
   * 页面的初始数据
   */
  data: {
    canvasWH: '',
    imgW: 0,
    imgH: 0,
    uploadFlag: false,
    imgUrls: [],
    maxHeight: ''
  },

  /* 上传图片 */
  uploadImg() {
    const query = wx.createSelectorQuery()
    query.select('#canvas').boundingClientRect(function(res) {
      wx.chooseImage({
        count: 1,
        sizeType: ['original', 'compressed'],
        // sizeType: ['compressed'],
        sourceType: ['album', 'camera'],
        success(res) {
          // 图片大小限制为 最大2M
          const imgSize = res.tempFiles[0].size
          console.log(res, imgSize, '已选择图片大小')

          if (imgSize > 1000000) {
            wx.showModal({
              title: '温馨提示',
              content: '图片最大不能超过1M',
              showCancel: false
            })
            return
          }
          
          const ctx = wx.createCanvasContext('canvasIn')
          const canvasW = res.width
          const canvasH = res.height
          ctx.fillStyle = '#fff'
          ctx.fillRect(0, 0, canvasW, canvasH)
          ctx.draw()

          // 获取图片信息
          wx.getImageInfo({
            src: res.tempFilePaths[0],
            success(imgInfo) {
              console.log(imgInfo, 'imgInfo')
              const imgW = imgInfo.width
              const imgH = imgInfo.height

              _this.setData({
                canvasWH: `width: ${imgW}px;height: ${imgH}px`,
                imgW,
                imgH
              })

              //  获取图片的大小
              ctx.drawImage(res.tempFilePaths[0], 0, 0, imgW, imgH)
              ctx.draw()
              //  展示新图片
              _this.showMiniImg()
            },
            fail(err) {
              console.log(err, '图片信息获取失败')
              wx.showModal({
                title: '温馨提示',
                content: '暂不支持此图片格式',
                showCancel: false
              })
            }
          })
        },
        fail (err) {
          console.log(err, '图片选择失败')
        }
      })
    })
    query.exec()
  },

  /* 展示小图 */
  showMiniImg() {
    let x = 0
    let y = 0
    let count = 0
    let imgUrls = []
    const {
      imgW,
      imgH
    } = _this.data

    const cutW = imgW / 3
    const cutH = imgH / 3

    const cfgSave = {
      x: 0,
      y: 0,
      width: cutW,
      height: cutH,
      destWidth: cutW,
      destHeight: cutH,
      canvasId: 'canvasIn'
    }
    _this.cutFlag = true

    const timer = setInterval(() => {
      if (_this.cutFlag) {
        _this.cutFlag = false
        console.log(count, 'cutFlag')
        switch (count) {
          case 0:
            x = 0
            y = 0
            break
          case 1:
            x = 1
            y = 0
            break
          case 2:
            x = 2
            y = 0
            break
          case 3:
            x = 0
            y = 1
            break
          case 4:
            x = 1
            y = 1
            break
          case 5:
            x = 2
            y = 1
            break
          case 6:
            x = 0
            y = 2
            break
          case 7:
            x = 1
            y = 2
            break
          case 8:
            x = 2
            y = 2
            break
          default:
            break
        }
        cfgSave.x = cutW * x
        cfgSave.y = cutH * y

        wx.canvasToTempFilePath({
          ...cfgSave,
          success(res) {
            console.log(res, '剪切')

            _this.cutFlag = true
            count++
            wx.showLoading({
              title: `裁剪中 ${count}/9`,
              mask: true
            })
            imgUrls.push(res.tempFilePath)
            if (count == 9) {
              if (imgUrls.length < 9) {
                imgUrls = []
                cut()
                return
              }
              wx.hideLoading()
              _this.setData({
                uploadFlag: true,
                imgUrls
              })
              clearInterval(timer)
            }
          },
          fail (err) {
            console.log(err , '剪切图片失败')
          }
        })
      }
    }, 100)
  },

  /* 保存图片(单图 / 所有) */
  saveImgHandle(e) {
    const {
      imgW,
      imgH,
      imgUrls
    } = _this.data

    const cutW = imgW / 3
    const cutH = imgH / 3

    const cfgSave = {
      x: 0,
      y: 0,
      width: cutW,
      height: cutH,
      destWidth: cutW,
      destHeight: cutH,
      canvasId: 'canvasIn',
    }

    if (e) { //保存单张图片
      switch (e.currentTarget.dataset.idx) {
        case 1:
          cfgSave.x = cutW * 0
          cfgSave.y = cutH * 0
          break
        case 2:
          cfgSave.x = cutW * 1
          cfgSave.y = cutH * 0
          break
        case 3:
          cfgSave.x = cutW * 2
          cfgSave.y = cutH * 0
          break
        case 4:
          cfgSave.x = cutW * 0
          cfgSave.y = cutH * 1
          break
        case 5:
          cfgSave.x = cutW * 1
          cfgSave.y = cutH * 1
          break
        case 6:
          cfgSave.x = cutW * 2
          cfgSave.y = cutH * 1
          break
        case 7:
          cfgSave.x = cutW * 0
          cfgSave.y = cutH * 2
          break
        case 8:
          cfgSave.x = cutW * 1
          cfgSave.y = cutH * 2
          break
        case 9:
          cfgSave.x = cutW * 2
          cfgSave.y = cutH * 2
          break
        default:
          break
      }
      wx.canvasToTempFilePath({
        ...cfgSave,
        success(res) {
          wx.saveImageToPhotosAlbum({
            filePath: res.tempFilePath,
            success(resPhoto) {
              wx.showToast({
                title: '保存成功'
              })
            }
          })
        }
      })
    } else { //保存所有
      let pathArr = []
      let x = 0
      let y = 0
      let count = 0
      _this.saveFlag = true

      const timer = setInterval(() => {
        if (_this.saveFlag) {

          _this.saveFlag = false
          console.log(count, 'saveFlag')
          switch (count) {
            case 0:
              x = 0
              y = 0
              break
            case 1:
              x = 1
              y = 0
              break
            case 2:
              x = 2
              y = 0
              break
            case 3:
              x = 0
              y = 1
              break
            case 4:
              x = 1
              y = 1
              break
            case 5:
              x = 2
              y = 1
              break
            case 6:
              x = 0
              y = 2
              break
            case 7:
              x = 1
              y = 2
              break
            case 8:
              x = 2
              y = 2
              break
            default:
              break
          }
          cfgSave.x = cutW * x
          cfgSave.y = cutH * y
          wx.canvasToTempFilePath({
            ...cfgSave,
            success(res) {
              console.log(res, '保存所有')

              pathArr.push(res.tempFilePath)
              count++
              wx.showLoading({
                title: `保存中${count}/9`,
              })
              _this.saveFlag = true
              if (count == 9) {
                clearInterval(timer)
                console.log(pathArr)
                // 保存到相册
                for (let i = 0; i < pathArr.length; i++) {
                  wx.saveImageToPhotosAlbum({
                    filePath: pathArr[i],
                    success(resPhoto) {
                      _this.saveFlag = true
                      if (i == pathArr.length - 1) {
                        wx.hideLoading()
                        wx.showToast({
                          title: '保存成功'
                        })
                      }
                    }
                  })
                }
              }
            }
          })
        }
      }, 100)
    }
  },

  /* 保存单张图片 */
  saveImg(e) {
    const {
      uploadFlag
    } = _this.data
    // 判断是否已上传图片
    if (uploadFlag) {
      wx.showModal({
        title: '温馨提示',
        content: '要将该图片保存到相册吗?',
        success(confirm) {
          if (confirm.confirm) {
            _this.photoAuthorization(e)
          }
        }
      })

    } else {
      wx.showModal({
        title: '温馨提示',
        content: '请先上传图片',
        showCancel: false
      })
    }

  },

  /* 一键保存 */
  saveAll() {
    const {
      uploadFlag
    } = _this.data
    // 判断是否已上传图片
    if (uploadFlag) {
      _this.photoAuthorization()
    } else {
      wx.showModal({
        title: '温馨提示',
        content: '请先上传图片',
        showCancel: false
      })
    }
  },

  /* 设置显示图片的最大高度为屏幕高 */
  setMaxHeight() {
    wx.getSystemInfo({
      success: function(res) {
        console.log(res)
        const windowH = res.windowHeight
        const maxHeight = parseInt(windowH / 3)
        _this.setData({
          maxHeight: `max-height: ${maxHeight}px`
        })
      },
    })
  },

  /* 相册授权 */
  photoAuthorization(event) {
    wx.getSetting({
      success(res) {
        if (res.authSetting['scope.writePhotosAlbum']) {
          // 已授权
          if (event) {
            _this.saveImgHandle(event)
          } else {
            _this.saveImgHandle()
          }
        } else {
          wx.authorize({
            scope: 'scope.writePhotosAlbum',
            success() {
              // 已授权
              if (event) {
                _this.saveImgHandle(event)
              } else {
                _this.saveImgHandle()
              }
            },
            fail() {
              // 未授权
              wx.showModal({
                title: '温馨提示',
                content: '需要获取相册权限',
                success(resOpenSetting) {
                  if (resOpenSetting.confirm) {
                    wx.openSetting({
                      success(res) {
                        if (res.authSetting['scope.writePhotosAlbum']) {
                          // 已授权
                          if (event) {
                            _this.saveImgHandle(event)
                          } else {
                            _this.saveImgHandle()
                          }
                        } else {
                          wx.showModal({
                            title: '温馨提示',
                            content: '未获取到授权信息',
                            showCancel: false
                          })
                        }
                      }
                    })
                  }
                }
              })
            }
          })
        }
      }
    })
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    _this = this
    _this.setMaxHeight()
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function() {

  }
})
page {
  height: 100%;
  background-color: #fff;
  overflow: hidden;
}

.sudoku {
  height: 100%;
}

.canvas-box {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: auto;
}

.canvas {
  min-width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
}

.canvas-in {
  z-index: 0;
}

.canvas-out {
  z-index: 99;
  background-color: #fff;
}

.imgs{
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  z-index: 999;
  background-color: #fff;
}

.imgs-box{
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  padding: 8rpx;
  box-sizing: border-box;
}

.img{
  flex-shrink: 0;
  width: 33.3%;
  padding: 5rpx;
  box-sizing: border-box;
}

.btns-box {
  position: fixed;
  right: 30rpx;
  bottom: 120rpx;
  z-index: 999;
  display: flex;
  justify-content: space-evenly;
  flex-direction: column;
  height: 300rpx;
}

.btn {
  color: #fff;
  width: 100rpx;
  height: 100rpx;
  border: none;
  border-radius: 50%;
}

.wx-button-cover-view-wrapper {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.wx-button-cover-view-inner {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.btn::after {
  border: none;
}

.btn-cut {
  background-color: rgba(44, 42, 165, 0.5);
}

.btn-save {
  background-color: rgba(200, 240, 56, 0.5);
}
posted @ 2019-07-06 13:15  有梦想的咸鱼-  阅读(2768)  评论(0编辑  收藏  举报