vue+element+vue-cropper实现上传裁剪功能

1.在用户上传前在before-upload钩子获取files文件,然后中断上传操作

beforeAvatarUpload (files) {
  this.filename = files.name
  this.openCropper(files)
  return false
}

然后在openCropper方法中用FileReader对读取文件并打开自己的cropper组件

openCropper (file) {
  var _this = this
  var reader = new FileReader()
  reader.onload = e => {
    let data
    if (typeof e.target.result === 'object') {
      // 把Array Buffer转化为blob 如果是base64不需要
      data = window.URL.createObjectURL(new Blob([e.target.result]))
    } else {
      data = e.target.result
    }
    _this.option.img = data
    _this.$refs.dialog.showDialog = true
  }
  // 转化为base64
  // reader.readAsDataURL(file)
  // 转化为blob
  reader.readAsArrayBuffer(file)
},

这是我cropper的界面和配置,不展开细讲

<custom-dialog title="封面裁剪"
               ref="dialog"
               width="50%"
               @confirm="handleConfirm"
              :dialogConfig="{ showFooter: true, name: '确定', headCenter: true }">
	 <div class="cropper-w">
	   <div class="cropper"
	        :style="{ width: '320px', height: '180px' }">
	     <vueCropper ref="cropper"
	                 v-if="crap"
	                 :img="option.img"
	                 :outputSize="option.size"
	                 :outputType="option.outputType"
	                 :info="option.info"
	                 :full="option.full"
	                 :canMove="option.canMove"
	                 :canMoveBox="option.canMoveBox"
	                 :original="option.original"
	                 :autoCrop="option.autoCrop"
	                 :autoCropWidth="option.autoCropWidth"
	                 :autoCropHeight="option.autoCropHeight"
	                 :fixedBox="option.fixedBox"></vueCropper>
	   </div>
	   <div class="tips">tips:滚动鼠标滚轮可进行缩放操作</div>
	 </div>
</custom-dialog>
option: {
   img: '', // 裁剪图片的地址
   info: false, // 裁剪框的大小信息
   outputSize: 1, // 剪切后的图片质量(0.1-1)
   full: true, // 输出原图比例截图 props名full
   outputType: 'png', // 裁剪生成额图片的格式
   canMove: true, // 能否拖动图片
   original: false, // 上传图片是否显示原始宽高
   canMoveBox: false, // 能否拖动截图框
   autoCrop: true, // 是否默认生成截图框
   autoCropWidth: 320,
   autoCropHeight: 180,
   fixedBox: true // 截图框固定大小
 },

用户上传成功后点确定就会调用handleConfirm方法

handleConfirm () {
  // 上传图片(点击上传按钮)
  if (!this.option.img) {
    return
  }
  // 输出
  // if (this.outputType !== 'blob') {
  this.$refs.cropper.getCropBlob((data) => {
    if (data.size > 2097152) {
      this.showMsg('图片大于2M,请进行裁剪或重新选择')
    }
    let blob = window.URL.createObjectURL(data)
    this.downImg = blob
    var base64;
    var img = new Image()
    img.src = blob
    var _that = this
    img.onload = function () {
      var that = this
      //生成比例
      var w = that.width,
        h = that.height,
        scale = w / h
      h = w / scale
      //生成canvas
      var canvas = document.createElement('canvas')
      var ctx = canvas.getContext('2d')
      canvas.width = w
      canvas.height = h
      ctx.drawImage(that, 0, 0, w, h)
      // 生成base64
      _that.cropperPic = canvas.toDataURL('image/jpeg', 0.8)
      _that.$refs.dialog.showDialog = false
      let files = _that.transformToFiles(_that.cropperPic, _that.filename)
      _that.temporaryCloseCropper = true
      // 最后一步是 手动调用element组件的上传方法
      // 举个例子
      _that.$refs.upload.$children[0].handleChange({ target: { files: [files] } })
    }
  })
},

transformToFiles方法是我在网上找的一个将base64转成files的方法

transformToFiles (dataurl, filename) {
   var arr = dataurl.split(','),
     mime = arr[0].match(/:(.*?);/)[1],
     bstr = atob(arr[1]),
     n = bstr.length,
     u8arr = new Uint8Array(n)
   while (n--) {
     u8arr[n] = bstr.charCodeAt(n)
   }
   return new File([u8arr], filename, { type: mime })
 }

然后最后,我们拿到新的file需要重新调用el-upload的上传方法

_that.$refs.upload.$children[0].handleChange({ target: { files: [files] } })

这样就可以继续上传了!

你可能感兴趣的:(Vue,element-ui,前端,vue.js,javascript,前端)