美文网首页惠学宝web技术
基于cropperjs实现Vue图片裁剪压缩上传功能

基于cropperjs实现Vue图片裁剪压缩上传功能

作者: Mr_xu_hxb | 来源:发表于2018-01-05 10:20 被阅读91次

    前段时间项目刚好需要用到图片预览裁剪压缩上传,而对于小白的我并没做过这方面的功能,可谓毫无头绪,于是上网查了下资料,发现了个很不错的插件

    好了,废话不多说,先上安装包

    npm或bower安装

    npm install cropper
    # or
    bower install cropper
    

    Github地址

     (https://github.com/fengyuanchen/cropperjs)
    

    引入cropperjs

    import Cropper from 'cropperjs'
    

    构建截图所要用到的div容器

      <!-- 图片裁剪遮罩层 -->  
      <div class="container" v-show="panel">  
          <div>  
            <img id="image" :src="url" alt="Picture">  
          </div>  
          <button type="button" class="cancelBtn" @click="cancelCrop">取消</button>
          <button type="button" class="sureBtn" @click="crop">确定</button>
      </div>
      <div>
        <img :src="pic">
        <-- 给input绑定一个监听内容变化的方法,拿到上传的文件 -->
        <input @change="updateHeadImg" type="file" accept="image/*"/>
      </div>
    

    添加遮罩层的样式和让image填充整个容器

    .container { z-index: 99; position: fixed; left: 0; top: 0; right: 0; bottom: 0; background:rgba(0,0,0,1);}
    #image {max-width: 100%;}
    .cancelBtn { position: absolute; left: 5%; bottom: 50px; width: 120px; height: 60px; line-height: 60px;         
     border:none; padding: 0; border-radius: 5px; background:white;}
    .sureBtn { position: absolute; right: 5%; bottom: 50px; width: 120px; height: 60px; line-height: 60px;       
     border:none; padding: 0; border-radius: 5px; background:white;}
    

    data

     data () {
      return {
        cropper: '',
        panel: false,
        croppable: false,
        url: '',
      }
    },
    

    初始化裁剪框

      let self = this
      this.cropper = new Cropper(image, {
        aspectRatio: 1, // 设置裁切框的宽高比
        viewMode: 2, // 限制裁剪框不超过画布的大小
        dragMode: 'move', // 在裁剪框外移动会移动原图
        background: false, // 显示容器的网格背景
        zoomable: true, // 是否可缩放图像
        autoCropArea: 1, // 裁剪区域的比例
        ready: function () {
          self.croppable = true
        }
      })
    

    本地图片上传到canvas

    updateHeadImg (e) {
      let files = e.target.files || e.dataTransfer.files
      let pattern = /(\.*.jpg$)|(\.*.png$)|(\.*.jpeg$)|(\.*.gif$)|(\.*.bmp$)/
      if (!files.length) return
      if (!pattern.test(files[0].name)) {
        this.pop = '仅支持jpg/jpeg/png/gif/bmp格式的照片'
        this.layer = 1
        return false
      }
      this.panel = true
      // 获取上传图片文件的url
      this.url = this.getObjectURL(files[0])
      // 每次替换图片要重新得到新的url
      if (this.cropper) {
        this.cropper.replace(this.url) // 替换图像的src并重建裁剪器
      }
      this.panel = true
    },
    

    获取上传图片文件的url

    getObjectURL (file) {
      var url = null
      if (window.createObjectURL !== undefined) { // basic
        url = window.createObjectURL(file)
      } else if (window.URL !== undefined) { // mozilla(firefox)
        url = window.URL.createObjectURL(file)
      } else if (window.webkitURL !== undefined) { // webkit or chrome
        url = window.webkitURL.createObjectURL(file)
      }
      return url
    },
    

    裁剪

    crop () {
      this.panel = false
      let croppedCanvas
      let roundedCanvas
      if (!this.croppable) {
        return
      }
      // Crop
      croppedCanvas = this.cropper.getCroppedCanvas()
      // Round
      roundedCanvas = this.getRoundedCanvas(croppedCanvas)
      // 将图片压缩 70%
      this.headerImage = roundedCanvas.toDataURL('image/jpeg', 0.7)
      // 上传到服务器
      this.postImg()
    },
    

    取消裁剪

    cancelCrop () {
      this.panel = false
    },
    

    Round

    getRoundedCanvas (sourceCanvas) {
      var canvas = document.createElement('canvas')
      var context = canvas.getContext('2d')
      var width = sourceCanvas.width
      var height = sourceCanvas.height
      canvas.width = width
      canvas.height = height
      context.imageSmoothingEnabled = true // 控制图像的缩放行为
      context.drawImage(sourceCanvas, 0, 0, width, height)
      context.globalCompositeOperation = 'destination-in' // 在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。
      context.beginPath()
      context.arc(width / 2, height / 2, Math.min(width, height) / 2, 0, 2 * Math.PI, true)
      context.fill()
      return canvas
    },
    

    上传到服务器

    postImg () {
      // 这边写图片的上传
      axios.post('接口', {'图片地址': this.headerImage}).then((res) => {
        console.log('成功')
      })
    },
    

    当初以为这样就完事了,可发现当再次进行上传的时候发现图片会下滑,翻看了一下文档,发现官方是使用动态添加裁剪容器的方法进行操作的。
    既然知道了每执行一次都要重新渲染画布,那就很简单了,我们把初始化事件添加到watch上,当重新选择的时候重新渲染画布

    /* 把画布清空 */
      if (document.querySelector('.cropper-container')) {
        document.querySelector('.cropper-container').remove()
      }
      this.cropper = ''
      // 重新渲染画布
      let image = document.getElementById('image')
      let self = this
      this.cropper = new Cropper(image, {
        aspectRatio: this.edEle.width / this.edEle.height, // 设置裁切框的宽高比
        viewMode: 2, // 限制裁剪框不超过画布的大小
        dragMode: 'move', // 在裁剪框外移动会移动原图
        background: false, // 显示容器的网格背景
        zoomable: true, // 是否可缩放图像
        autoCropArea: 1, // 裁剪区域的比例
        ready: function () {
          self.croppable = true
        }
      })
    

    小白初来驾到,如有错误请告知,让我们互相学习学习

    相关文章

      网友评论

      本文标题:基于cropperjs实现Vue图片裁剪压缩上传功能

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