vue項目中實現圖片裁剪功能

原文地址

https://github.com/MY729/pict...html

在vue項目中實現圖片裁剪功能

演示地址

https://my729.github.io/picture-crop-demo/dist/#/vue

前言

使用 cropperjs插件 和 原生canvas 兩種方式實現圖片裁剪功能

使用cropperjs插件

安裝cropperjs

yarn install cropperjs

初始化一個canvas元素,並在上面繪製圖片

<canvas :id="data.src" ref="canvas"></canvas>
// 在canvas上繪製圖片
drawImg () {
  this.$nextTick(() => {
    // 獲取canvas節點
    let canvas = document.getElementById(this.data.src)
    if (canvas) {
      // 設置canvas的寬爲canvas的父元素寬度,寬高比3:2
      let parentEle = canvas.parentElement
      canvas.width = parentEle.offsetWidth
      canvas.height = 2 * parentEle.offsetWidth / 3
      let ctx = canvas.getContext('2d')
      ctx.clearRect(0, 0, canvas.width, canvas.height)
      let img = new Image()
      img.crossOrigin = 'Anonymous'
      img.src = this.data.src
      img.onload = function () {
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
      }
    }
  })
}
若是遇到canvas跨域繪製圖片報錯,設置圖片img.crossOrigin = 'Anonymous',而且服務器響應頭設置Access-Control-Allow-Origin:*

建立cropperjs

// 引入
import Cropper from 'cropperjs'

// 顯示裁剪框
initCropper () {
  let cropper = new Cropper(this.$refs.canvas, {
    checkCrossOrigin: true,
    viewMode: 2,
    aspectRatio: 3 / 2
  })
}
更多方法和屬性,參考官網: https://github.com/fengyuanchen/cropperjs

具體實現,能夠查看源碼的cropper.vuecropper.one.vue組件:git

cropper.vue組件:https://github.com/MY729/pict...
cropper.one.vue組件:https://github.com/MY729/pict...github

使用canvas實現圖片裁剪

支持鼠標繪製裁剪框,並移動裁剪框

思路:

  • 在canvas上繪製圖片爲背景
  • 監聽鼠標點擊、移動、鬆開事件
canvas的isPointInPath()方法:
若是給定的點的座標位於路徑以內的話(包括路徑的邊),不然返回 false

具體實現可查看源碼cropper.canvas.vue組件: https://github.com/MY729/pict...canvas

cropImg () {
  let canvas = document.getElementById(this.data.img_url)
  let ctx = canvas.getContext('2d')
  let img = new Image()
  img.onload = function () {
    ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
  }
  img.src = this.data.src
  let drag = false // 是否拖動矩形
  let flag = false // 是否繪製矩形
  let rectWidth = 0 // 繪製矩形的寬
  let rectHeight = 0 // 繪製矩形的高
  let clickX = 0 // 矩形開始繪製X座標
  let clickY = 0 // 矩形開始繪製Y座標
  let dragX = 0 // 當要拖動矩形點擊時X座標
  let dragY = 0 // 當要拖動矩形點擊時Y座標
  let newRectX = 0 // 拖動變化後矩形開始繪製的X座標
  let newRectY = 0 // 拖動變化後矩形開始繪製的Y座標
  // 鼠標按下
  canvas.onmousedown = e => {
    // 每次點擊前若是有繪製好的矩形框,經過路徑繪製出來,用於下面的判斷
    ctx.beginPath()
    ctx.setLineDash([6, 6])
    ctx.moveTo(newRectX, newRectY)
    ctx.lineTo(newRectX + rectWidth, newRectY)
    ctx.lineTo(newRectX + rectWidth, newRectY + rectHeight)
    ctx.lineTo(newRectX, newRectY + rectHeight)
    ctx.lineTo(newRectX, newRectY)
    ctx.strokeStyle = 'green'
    ctx.stroke()
    // 每次點擊,經過判斷鼠標點擊的點在矩形框內仍是外,來決定從新繪製仍是移動矩形框
    if (ctx.isPointInPath(e.offsetX, e.offsetY)) {
      drag = true
      dragX = e.offsetX
      dragY = e.offsetY
      clickX = newRectX
      clickY = newRectY
    } else {
      ctx.clearRect(0, 0, canvas.width, canvas.height)
      ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
      flag = true
      clickX = e.offsetX
      clickY = e.offsetY
      newRectX = e.offsetX
      newRectY = e.offsetY
    }
  }
  // 鼠標擡起
  canvas.onmouseup = () => {
    if (flag) {
      flag = false
      this.sureCrop(clickX, clickY, rectWidth, rectHeight)
    }
    if (drag) {
      drag = false
      this.sureCrop(newRectX, newRectY, rectWidth, rectHeight)
    }
  }
  // 鼠標移動
  canvas.onmousemove = (e) => {
    if (flag) {
      ctx.clearRect(0, 0, canvas.width, canvas.height)
      ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
      rectWidth = e.offsetX - clickX
      rectHeight = e.offsetY - clickY

      ctx.beginPath()
      ctx.strokeStyle = '#FF0000'
      ctx.strokeRect(clickX, clickY, rectWidth, rectHeight)
      ctx.closePath()
    }
    if (drag) {
      ctx.clearRect(0, 0, canvas.width, canvas.height)
      ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
      ctx.beginPath()
      newRectX = clickX + e.offsetX - dragX
      newRectY = clickY + e.offsetY - dragY
      ctx.strokeStyle = 'yellow'
      ctx.strokeRect(newRectX, newRectY, rectWidth, rectHeight)
      ctx.closePath()
    }
  }
},
// 拿到裁剪後的參數,可自行處理圖片
sureCrop (x, y, width, height) {
  let canvas = document.getElementById(this.data.img_url + 'after')
  // 設置canvas的寬爲canvas的父元素寬度,寬高比3:2
  let parentEle = canvas.parentElement
  canvas.width = parentEle.offsetWidth
  canvas.height = 2 * parentEle.offsetWidth / 3
  let ctx = canvas.getContext('2d')
  let img = new Image()
  img.src = this.data.src
  img.onload = function () {
    ctx.beginPath()
    ctx.moveTo(x, y)
    ctx.lineTo(x + width, y)
    ctx.lineTo(x + width, y + height)
    ctx.lineTo(x, y + height)
    ctx.clip()
    ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
  }
  ctx.stroke()
}

源碼地址

https://github.com/MY729/pict...跨域

能夠直接clone項目,本地運行查看代碼和效果bash

相關文章
相關標籤/搜索