使用vue3和elementPlus實現上傳圖片裁剪
參考文章地址:https://chengpeiquan.com/article/vue-picture-cropper.html#demo
<template>
<!-- 選擇圖片 -->
<br/>
<label for="explore" class="labelBtn">
<input
style="display: none;"
id="explore"
ref="uploadInput"
type="file"
accept="image/jpg, image/jpeg, image/png, image/gif"
@change="selectFile"
/>
+ 點選上傳封面圖片
</label>
{{ result.fileName }}
<br/>
<br/>
<!-- 選擇圖片 -->
<!-- 結果預覽區 -->
<div v-if="result.dataURL && result.blobURL">
<p>裁切後的 Base64 圖片預覽:</p>
<div class="preview">
<img :src="result.dataURL" alt="組合式 API" />
</div>
<p>裁切後的 Blob 圖片預覽:</p>
<div class="preview">
<img :src="result.blobURL" alt="組合式 API" />
</div>
<p>可以按 F12 檢視列印的 base64 / blob / file 結果</p>
</div>
<!-- 結果預覽區 -->
<!-- 用於裁切的彈窗 -->
<el-dialog v-model="isShowDialog" title="圖片裁切" :close-on-click-modal="false">
<template #footer>
<el-button @click="isShowDialog = false; result.fileName = ''">取消</el-button>
<el-button @click="clear">清除</el-button>
<el-button @click="reset">重置</el-button>
<el-button type="primary" @click="getResult">裁切</el-button>
</template>
<!-- 圖片裁切外掛 -->
<VuePictureCropper
:boxStyle="{
width: '100%',
height: '100%',
backgroundColor: '#f8f8f8',
margin: 'auto',
}"
:img="pic"
:options="{
viewMode: 1,
dragMode: 'crop',
aspectRatio: 16 / 9,
}"
/>
<!-- 圖片裁切外掛 -->
</el-dialog>
<!-- 用於裁切的彈窗 -->
</template>
<script setup>
import { reactive, ref } from 'vue'
import VuePictureCropper, { cropper } from 'vue-picture-cropper'
const isShowDialog = ref(false)
const uploadInput = ref(null)
const pic = ref('')
const result = reactive({
dataURL: '',
blobURL: '',
fileName: ''
})
/**
* 選擇圖片
*/
const selectFile = (e) => {
// 重置上一次的結果
result.dataURL = ''
result.blobURL = ''
// 如果有多個裁剪框,也需要重置掉裁剪目標的值,避免使用同一張圖片無法觸發watch
pic.value = ''
// 獲取選取的檔案
const target = e.target
const { files } = target
if (!files) return
const file = files[0]
result.fileName = file.name
// 轉換為base64傳給裁切元件
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = () => {
// 更新裁切彈窗的圖片源
pic.value = String(reader.result)
// 顯示裁切彈窗
isShowDialog.value = true
// 清空已選擇的檔案
if (!uploadInput.value) return
uploadInput.value.value = ''
}
}
/**
* 獲取裁切結果
*/
const getResult = async () => {
console.log(cropper)
// 獲取生成的base64圖片地址
const base64 = cropper.getDataURL()
// 獲取生成的blob檔案資訊
const blob = await cropper.getBlob()
// 獲取生成的file檔案資訊
const file = await cropper.getFile({
fileName: result.fileName
})
console.log({ base64, blob, file })
// 把base64賦給結果展示區
result.dataURL = base64
try {
result.blobURL = URL.createObjectURL(blob)
} catch (e) {
result.blobURL = ''
}
// 隱藏裁切彈窗
isShowDialog.value = false
result.fileName = ''
}
/**
* 清除裁切框
*/
const clear = () => {
cropper.clear()
}
/**
* 重置預設的裁切區域
*/
const reset = () => {
cropper.reset()
}
</script>
<style scoped>
.labelBtn {
background: #fff;
border: 1px solid #eee;
border-radius: 5px;
padding: 10px 20px;
}
</style>