溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么在vue項目中實(shí)現(xiàn)一個圖片裁剪功能

發(fā)布時間:2021-03-11 17:07:02 來源:億速云 閱讀:179 作者:Leah 欄目:web開發(fā)

今天就跟大家聊聊有關(guān)怎么在vue項目中實(shí)現(xiàn)一個圖片裁剪功能,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

使用cropperjs插件

安裝cropperjs

yarn install cropperjs

初始化一個canvas元素,并在上面繪制圖片

<canvas :id="data.src" ref="canvas"></canvas>
// 在canvas上繪制圖片
drawImg () {
 this.$nextTick(() => {
 // 獲取canvas節(jié)點(diǎn)
 let canvas = document.getElementById(this.data.src)
 if (canvas) {
 // 設(shè)置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跨域繪制圖片報錯,設(shè)置圖片img.crossOrigin = 'Anonymous',并且服務(wù)器響應(yīng)頭設(shè)置Access-Control-Allow-Origin:*

創(chuàng)建cropperjs

// 引入
import Cropper from 'cropperjs'

// 顯示裁剪框
initCropper () {
 let cropper = new Cropper(this.$refs.canvas, {
 checkCrossOrigin: true,
 viewMode: 2,
 aspectRatio: 3 / 2
 })
}

更多方法和屬性,參考官網(wǎng): https://github.com/fengyuanchen/cropperjs

具體實(shí)現(xiàn),可以查看源碼的cropper.vue 或 cropper.one.vue組件:

cropper.vue組件:https://github.com/MY729/picture-crop-demo/blob/master/src/components/cropper.vue
cropper.one.vue組件:https://github.com/MY729/picture-crop-demo/blob/master/src/components/cropper.one.vue

使用canvas實(shí)現(xiàn)圖片裁剪

支持鼠標(biāo)繪制裁剪框,并移動裁剪框

思路:

  • 在canvas上繪制圖片為背景

  • 監(jiān)聽鼠標(biāo)點(diǎn)擊、移動、松開事件

canvas的isPointInPath()方法: 如果給定的點(diǎn)的坐標(biāo)位于路徑之內(nèi)的話(包括路徑的邊),否則返回 false

具體實(shí)現(xiàn)可查看源碼cropper.canvas.vue組件: https://github.com/MY729/picture-crop-demo/blob/master/src/components/cropper.canvas.vue

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坐標(biāo)
 let clickY = 0 // 矩形開始繪制Y坐標(biāo)
 let dragX = 0 // 當(dāng)要拖動矩形點(diǎn)擊時X坐標(biāo)
 let dragY = 0 // 當(dāng)要拖動矩形點(diǎn)擊時Y坐標(biāo)
 let newRectX = 0 // 拖動變化后矩形開始繪制的X坐標(biāo)
 let newRectY = 0 // 拖動變化后矩形開始繪制的Y坐標(biāo)
 // 鼠標(biāo)按下
 canvas.onmousedown = e => {
 // 每次點(diǎn)擊前如果有繪制好的矩形框,通過路徑繪制出來,用于下面的判斷
 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()
 // 每次點(diǎn)擊,通過判斷鼠標(biāo)點(diǎn)擊的點(diǎn)在矩形框內(nèi)還是外,來決定重新繪制還是移動矩形框
 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
 }
 }
 // 鼠標(biāo)抬起
 canvas.onmouseup = () => {
 if (flag) {
 flag = false
 this.sureCrop(clickX, clickY, rectWidth, rectHeight)
 }
 if (drag) {
 drag = false
 this.sureCrop(newRectX, newRectY, rectWidth, rectHeight)
 }
 }
 // 鼠標(biāo)移動
 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()
 }
 }
},
// 拿到裁剪后的參數(shù),可自行處理圖片
sureCrop (x, y, width, height) {
 let canvas = document.getElementById(this.data.img_url + 'after')
 // 設(shè)置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()
}

看完上述內(nèi)容,你們對怎么在vue項目中實(shí)現(xiàn)一個圖片裁剪功能有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

vue
AI