在vue中使用vue-cropper圖片裁剪並上傳圖片
思路:封裝一個對話框(Modal),里面包含一個vue-cropper,用於ant-upload上傳文件時調用彈出此對話框讓用戶編輯此圖片.裁剪完emit一個事件,然后上傳這個編輯后的圖片(file)
先是對vue-cropper進行再封裝
該組件就對外''暴露 "2個操作 1. 傳入圖像數據並打開對話框 2. 圖像處理完后返回圖像數據 這使用起來方便
碼來:src\components\common\cropper-modal.vue
<template>
<a-modal
:visible="visible"
title="請裁剪圖片"
:maskClosable="false"
:confirmLoading="confirmLoading"
@cancel="handleCancel"
@ok="handleOk"
>
<div class="cropper-wrapper">
<vue-cropper
ref="cropper"
:img="img"
:info="true"
:original="true"
:autoCrop="options.autoCrop"
:autoCropWidth="options.autoCropWidth"
:autoCropHeight="options.autoCropHeight"
:fixedBox="options.fixedBox"
></vue-cropper>
</div>
</a-modal>
</template>
<script>
import { VueCropper } from 'vue-cropper'
export default {
components: {
VueCropper,
},
data() {
return {
// ant-modal相關配置
visible: false,
confirmLoading: false,
// vue-cropper相關配置 詳細的可以去github上看文檔
img: null, //要裁剪的圖像資源 可選項: url地址 || base64 || blob
options: {
autoCrop: true, //是否默認生成截圖框
autoCropWidth: 200, //默認生成截圖框寬度
autoCropHeight: 200, //默認生成截圖框高度
fixedBox: true, //固定截圖框大小 不允許改變
},
}
},
methods: {
// 調用此方法需傳入一個 [url地址 || base64 || blob]
// 父組件調用: this.$refs['cropperModal'].edit(參數)
edit(image) {
this.img = image
this.visible = true
},
// 監聽對話框的OK/Cancel按鈕的點擊事件
handleOk() {
const that = this
that.confirmLoading = true
// 獲取截圖的base64 數據
// getCropBlob獲取二進制數據
this.$refs.cropper.getCropData((data) => {
//將裁剪侯后的圖片對象射給**父組件**,然后關閉對話框
that.$emit('ok', data)
that.handleCancel()
})
},
handleCancel(e) {
this.visible = false
},
},
}
</script>
<style lang="scss" scoped>
.cropper-wrapper {
width: 100%;
height: 400px;
}
</style>
父組件是用了ant-design-vue的upload組件
關鍵代碼如下:顯示為一個按鈕,點擊更換頭像后彈出文件選擇框,再選擇文件后先是調用beforeUpload
判斷文件類型,滿足條件然后調用
handleUploadChange
函數
@ok="handleOK"
就是在圖片裁剪后 emit的ok事件
<a-upload
:before-upload="beforeUpload"
:show-upload-list="false"
:custom-request="function(){}"
@change="handleUploadChange"
>
<a-button type="primary">更換頭像</a-button>
</a-upload>
<cropper-modal @ok="handleOK" ref="cropperModal" />
// 在父組件的methods中
// 選擇文件后且beforeUpload返回為true后會調用這個方法
handleUploadChange(info) {
// 這個回調函數的參數是個File對象,所以要用FileReader將對象轉換成 data-uri (base64) 對象,才能給vue-cropper
var reader = new FileReader()
const _this = this
// 當文件處理完成的回調函數
reader.onload = function (e) {
// e.target.result 該屬性表示目標對象的DataURL
// 然后調用cropperModal的edit方法使得對話框可見
_this.$refs['cropperModal'].edit(e.target.result)
}
// 記錄原始的文件名字,用於DataURL(base64)轉成file對象,不轉就可以不用
this.tmpImgName = info.file.name
// 文件處理 file=>base64
reader.readAsDataURL(info.file.originFileObj)
},
// 對文件格式校驗(ant-upload選擇文件框是所有類型的)
beforeUpload(file) {
var fileType = file.type
console.log(file.type)
if (fileType.indexOf('image') < 0) {
this.$message.warning('請上傳圖片')
return false
}
},
// 然后這里可以調用api請求上傳圖片
handleOK(data) {
console.log(data)
let file = this.dataURLtoFile(data, this.tmpImgName)
console.log(file)
// ....省略api請求 2種格式的對象都拿到了 怎么請求不用說了吧
},
// 將base64轉換為文件 百度隨便找的 看需求使用
dataURLtoFile(dataurl, filename) {
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], filename, { type: mime })
},
附帶一個axios上傳multipart格式的文件方法
// 上傳頭像 File類型
uploadAvatar(file) {
let param = new FormData() // 創建form對象
param.append('file', file) // 通過append向form對象添加數據
// param.append('chunk', '0') // 添加form表單中其他數據
let config = {
headers: { 'Content-Type': 'multipart/form-data' }
}
return axios.post('/upload/avatar', param, config)
},
參考鏈接
文檔教程:http://github.xyxiao.cn/vue-cropper/example/
他人教程:https://www.jianshu.com/p/4024cf503380
結合antv:https://blog.csdn.net/qq_36111804/article/details/94599536
HTML5 file對象和blob對象的互相轉換 https://www.jianshu.com/p/5b44c41adfe2