前段時(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
(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í)