欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

微信小程序圖片裁剪工具 wx-cropper優化

程序员文章站 2024-03-13 23:35:28
...
wx-cropper源碼地址,感謝作者分享源碼。引用部分不用改動。優化部分我將詳細講解。
https://github.com/we-plugin/we-cropper

優化

  1. 獲取頁面高度,動態改變canvas高度時,應在onload回調函數中獲取,不然會出現bug,獲取的是上一頁的高度。
  onLoad(option) {
    let device = wx.getSystemInfoSync()
    let height = device.windowHeight - 50;
    this.setData({
      ["cropperOpt.height"]: height,
      ["cropperOpt.cut.y"]: (height - 300) / 2,
    })
 }   
  1. 圖片如果模糊,是因爲手機像素比的問題,具體詳見https://github.com/we-plugin/we-cropper/wiki/FAQ。
 // 所有参数乘设备像素比
      imgLeft = imgLeft * devicePixelRatio
      imgTop = imgTop * devicePixelRatio
      scaleWidth = scaleWidth * devicePixelRatio
      scaleHeight = scaleHeight * devicePixelRatio
      x = x * devicePixelRatio
      y = y * devicePixelRatio
      width = width * devicePixelRatio
      height = height * devicePixelRatio
  1. 裁切后圖片體積太大,解決該問題需要wx自帶api進行質量壓縮
wx.canvasToTempFilePath({
          canvasId: 'hideCanvas',
          x,
          y,
          width,
          height,
          destWidth: _that.data.uploadWidth,
          destHeight: _that.data.uploadHeight,
          fileType:'jpg',	//必須是jpg格式,png會使quality失效
          quality,	//圖片質量,參數為從零到一,0.7比較合適,壓縮完差不多100KB左右。
          success(res) {
            const tmpPath = res.tempFilePath;
            _that.afterGetPath(tmpPath)
          },
          fail(e) {
            console.log(e)
          }
        })
  1. 裁剪后會自動調用上一頁面的afterCuttingImg函數,參數為圖片的臨時路徑

項目源代碼

import WeCropper from './we-cropper/we-cropper.js'
const App = getApp();

const device = wx.getSystemInfoSync()
const width = device.windowWidth
const pixelRatio = device.pixelRatio
Page({
  data: {
    cropperOpt: {
      id: 'cropper',
      width,
      // height,
      pixelRatio,
      scale: 2.5,
      zoom: 8,
      cut: {
        x: (width - 300) / 2,
        // y: (height - 300) / 2,
        width: 300,
        height: 300
      }
    },
  },
  touchStart(e) {
    this.wecropper.touchStart({
      touches: e.touches.filter(i => i.x !== undefined)
    })
  },
  touchMove(e) {
    this.wecropper.touchMove({
      touches: e.touches.filter(i => i.x !== undefined)
    })
  },
  touchEnd(e) {
    this.wecropper.touchEnd()
  },

  uploadTap() {
    const self = this

    wx.chooseImage({
      count: 1, // 默认9
      sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
      sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
      success(res) {
        const src = res.tempFilePaths[0]
        //  获取裁剪图片资源后,给data添加src属性及其值

        self.wecropper.pushOrign(src)
      }
    })
  },

  //裁剪
  btnHandle() {
    //高清裁剪
    let quality = 0.7;
    if (this.data.quality) {
      quality = 1;
    }
    // if (this.data.quality) {
      let _that = this;
      // 点击了裁剪按钮
      let devicePixelRatio = this.data.cropperOpt.pixelRatio
      let { imgLeft, imgTop, scaleWidth, scaleHeight } = this.wecropper // 获取图片在原画布坐标位置及宽高
      let { x, y, width, height } = this.wecropper.cut // 获取裁剪框位置及大小
      // 所有参数乘设备像素比
      imgLeft = imgLeft * devicePixelRatio
      imgTop = imgTop * devicePixelRatio
      scaleWidth = scaleWidth * devicePixelRatio
      scaleHeight = scaleHeight * devicePixelRatio
      x = x * devicePixelRatio
      y = y * devicePixelRatio
      width = width * devicePixelRatio
      height = height * devicePixelRatio

      const targetCtx = wx.createCanvasContext('hideCanvas') // 这里是目标canvas画布的id值

      targetCtx.drawImage(this.data.cropperOpt.src, imgLeft, imgTop, scaleWidth, scaleHeight) // tmp代表被裁剪图片的临时路径

      targetCtx.draw(false, function (e) {
        wx.canvasToTempFilePath({
          canvasId: 'hideCanvas',
          x,
          y,
          width,
          height,
          destWidth: _that.data.uploadWidth,
          destHeight: _that.data.uploadHeight,
          fileType:'jpg',
          quality,
          success(res) {
            const tmpPath = res.tempFilePath;
            _that.afterGetPath(tmpPath)
          },
          fail(e) {
            console.log(e)
          }
        })
      })
    // } else {
    //   this.wecropper.getCropperImage((avatar) => {
    //     this.afterGetPath(avatar)
    //   })
    // }
  },
  afterGetPath(avatar) {
    if (avatar) {
      //  获取到裁剪后的图片
      var pages = getCurrentPages();
      if (pages.length > 1) {
        //上一个页面实例对象
        var prePage = pages[pages.length - 2];
        //关键在这里
        try {
          prePage.afterCuttingImg(avatar)
        } catch (e) {
          console.warn("please setting afterCuttingImg function to receive img url");
        }
        wx.navigateBack();
      }

    } else {
      console.log('获取图片失败,请稍后重试')
    }
  },
  onLoad(option) {
    let device = wx.getSystemInfoSync()
    let height = device.windowHeight - 50;
    this.setData({
      ["cropperOpt.height"]: height,
      ["cropperOpt.cut.y"]: (height - 300) / 2,
    })

    const { cropperOpt } = this.data
    
    //裁图质量
    if (option.quality) {
      this.setData({
        quality: true
      })
    }
    this.setData({
      uploadWidth:option.width,
      uploadHeight:option.height
    })

    if (option.src) {
      cropperOpt.src = option.src
      new WeCropper(cropperOpt)
        .on('ready', (ctx) => {
          // console.log(`wecropper is ready for work!`)
        })
        .on('beforeImageLoad', (ctx) => {
          // console.log(`before picture loaded, i can do something`)
          // console.log(`current canvas context:`, ctx)
          wx.showToast({
            title: '上传中',
            icon: 'loading',
            duration: 20000
          })
        })
        .on('imageLoad', (ctx) => {
          // console.log(`picture loaded`)
          // console.log(`current canvas context:`, ctx)
          wx.hideToast()
        })
        .on('beforeDraw', (ctx, instance) => {
          // console.log(`before canvas draw,i can do something`)
          // console.log(`current canvas context:`, ctx)
        })
        .updateCanvas()
    }
  }
})