基于cropperjs實(shí)現(xiàn)Vue圖片裁剪壓縮上傳功能

前段時(shí)間項(xiàng)目剛好需要用到圖片預(yù)覽裁剪壓縮上傳,而對(duì)于小白的我并沒(méi)做過(guò)這方面的功能,可謂毫無(wú)頭緒,于是上網(wǎng)查了下資料,發(fā)現(xiàn)了個(gè)很不錯(cuò)的插件

好了,廢話不多說(shuō),先上安裝包

npm或bower安裝

npm install cropper
# or
bower install cropper

Github地址

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

引入cropperjs

import Cropper from 'cropperjs'

構(gòu)建截圖所要用到的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綁定一個(gè)監(jiān)聽(tīng)內(nèi)容變化的方法,拿到上傳的文件 -->
    <input @change="updateHeadImg" type="file" accept="image/*"/>
  </div>

添加遮罩層的樣式和讓image填充整個(gè)容器

.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, // 設(shè)置裁切框的寬高比
    viewMode: 2, // 限制裁剪框不超過(guò)畫(huà)布的大小
    dragMode: 'move', // 在裁剪框外移動(dòng)會(huì)移動(dòng)原圖
    background: false, // 顯示容器的網(wǎng)格背景
    zoomable: true, // 是否可縮放圖像
    autoCropArea: 1, // 裁剪區(qū)域的比例
    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)
  // 上傳到服務(wù)器
  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' // 在源圖像中顯示目標(biāo)圖像。只有源圖像內(nèi)的目標(biāo)圖像部分會(huì)被顯示,源圖像是透明的。
  context.beginPath()
  context.arc(width / 2, height / 2, Math.min(width, height) / 2, 0, 2 * Math.PI, true)
  context.fill()
  return canvas
},

上傳到服務(wù)器

postImg () {
  // 這邊寫(xiě)圖片的上傳
  axios.post('接口', {'圖片地址': this.headerImage}).then((res) => {
    console.log('成功')
  })
},

當(dāng)初以為這樣就完事了,可發(fā)現(xiàn)當(dāng)再次進(jìn)行上傳的時(shí)候發(fā)現(xiàn)圖片會(huì)下滑,翻看了一下文檔,發(fā)現(xiàn)官方是使用動(dòng)態(tài)添加裁剪容器的方法進(jìn)行操作的。
既然知道了每執(zhí)行一次都要重新渲染畫(huà)布,那就很簡(jiǎn)單了,我們把初始化事件添加到watch上,當(dāng)重新選擇的時(shí)候重新渲染畫(huà)布

/* 把畫(huà)布清空 */
  if (document.querySelector('.cropper-container')) {
    document.querySelector('.cropper-container').remove()
  }
  this.cropper = ''
  // 重新渲染畫(huà)布
  let image = document.getElementById('image')
  let self = this
  this.cropper = new Cropper(image, {
    aspectRatio: this.edEle.width / this.edEle.height, // 設(shè)置裁切框的寬高比
    viewMode: 2, // 限制裁剪框不超過(guò)畫(huà)布的大小
    dragMode: 'move', // 在裁剪框外移動(dòng)會(huì)移動(dòng)原圖
    background: false, // 顯示容器的網(wǎng)格背景
    zoomable: true, // 是否可縮放圖像
    autoCropArea: 1, // 裁剪區(qū)域的比例
    ready: function () {
      self.croppable = true
    }
  })

小白初來(lái)駕到,如有錯(cuò)誤請(qǐng)告知,讓我們互相學(xué)習(xí)學(xué)習(xí)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容