Vue3結(jié)合vue-cropper實(shí)現(xiàn)圖片裁剪預(yù)覽功能
一、介紹??
Vue-Cropper?? 是一個(gè)基于 Vue.js 的圖片裁剪組件庫,專為 Web 應(yīng)用設(shè)計(jì)。當(dāng)你在網(wǎng)上搜索的時(shí)候發(fā)現(xiàn)還有一個(gè)叫cropper的庫,下面是他們的區(qū)別:

二、快速上手
//npm 安裝 npm install vue-cropper //yarn 安裝 yarn add vue-cropper
對(duì)該插件進(jìn)行封裝,使用vue3 + ts
<script lang="ts" setup>
import 'vue-cropper/dist/index.css'
import { VueCropper } from 'vue-cropper'
const emit = defineEmits(['realTime'])
const props = defineProps({
width: { type: Number, default: 640 },
height: { type: Number, default: 740 }
})
const options = reactive({
img: '',
autoCrop: true,
autoCropWidth: 640,
autoCropHeight: 740,
fillColor: '#fff', // 裁剪框填充顏色
fixedBox: true // 固定裁剪框
})
const cropperInstance = ref()
const blobData = ref(new Blob())
const init = () => {
options.img = ''
}
const selectImg = async (e: Event) => {
const file = (e.target as HTMLInputElement).files?.[0]
if (!file) return
const reader = new FileReader()
reader.onload = async e => {
const img = new Image()
img.onload = async () => {
// 強(qiáng)制放大到最小尺寸
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')!
// 設(shè)置 canvas 尺寸
canvas.width = img.width
canvas.height = img.height
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
options.img = canvas.toDataURL()
await nextTick()
// 等待 DOM 更新后設(shè)置裁剪框
setFixedCropBox()
}
img.src = e.target!.result as string
}
reader.readAsDataURL(file)
}
const setFixedCropBox = () => {
if (!cropperInstance.value?.cropper) return
// 正確訪問cropper實(shí)例
const cropper = cropperInstance.value.cropper
// 獲取容器真實(shí)尺寸
const containerWidth = cropper.containerData.width
const containerHeight = cropper.containerData.height
// 計(jì)算居中位置
const left = (containerWidth - props.width) / 2
const top = (containerHeight - props.height) / 2
// 正確調(diào)用方法
cropper.setCropBoxData({
width: props.width,
height: props.height,
left,
top
})
}
// 實(shí)時(shí)預(yù)覽
const realTime = (data: any) => {
emit('realTime', data.html)
}
// 獲取截圖的數(shù)據(jù) getCropBlob => blob數(shù)據(jù)
const tailoring = (): Promise<Blob> => {
return new Promise((resolve, reject) => {
if (!cropperInstance.value) {
reject(new Error('裁剪組件未初始化'))
return
}
cropperInstance.value.getCropBlob((data: Blob) => {
if (data) {
blobData.value = data
resolve(data)
} else {
reject(new Error('裁剪失敗,未獲取到 Blob'))
}
})
})
}
// 旋轉(zhuǎn)
const rotateLeft = () => {
if (!cropperInstance.value) return
cropperInstance.value.rotateLeft()
}
const rotateRight = () => {
if (!cropperInstance.value) return
cropperInstance.value.rotateRight()
}
onMounted(() => {
if (props.width && props.height) {
options.autoCropWidth = props.width
options.autoCropHeight = props.height
}
})
defineExpose({ options, selectImg, realTime, tailoring, blobData, init, rotateLeft, rotateRight })
</script>
<template>
<vue-cropper
ref="cropperInstance"
:img="options.img"
:autoCrop="options.autoCrop"
:autoCropWidth="options.autoCropWidth"
:autoCropHeight="options.autoCropHeight"
:fixedBox="options.fixedBox"
:fillColor="options.fillColor"
@real-time="realTime"
/>
</template>父組件進(jìn)行使用
<el-form-item>
<div class="flex items-center gap-10px">
<span>公告圖片</span>
<!-- <el-button size="small" type="primary" class="mx-0" @click="openUpload">
<el-icon class="mr-3px"><Upload /></el-icon> 上傳</el-button
> -->
<el-button :type="form.backgroundImage ? 'success' : 'primary'" @click="openUpload">
<el-icon class="mr-3px"><Upload /></el-icon>
{{ form.backgroundImage ? '重新上傳' : '上傳' }}</el-button
>
<el-button class="mx-0" type="danger" :icon="Delete" @click="form.backgroundImage = ''"></el-button>
<div class="text-slate text-xs">建議:寬高640*740,png或jpg/jpeg格式,小于2M</div>
</div>
<input type="file" name="" ref="uploadRef" class="hidden" @change="handleCaptureUpload" />
</el-form-item>
<!-- 圖片預(yù)覽裁剪 -->
<el-dialog
v-model="showCaptureVisible"
title="圖片預(yù)覽裁剪"
width="50%"
@close="closeCapture"
top="5vh"
draggable
destroy-on-close
>
<div class="w-full h-78vh mt-10px flex justify-center items-center">
<Cropper ref="cropper" :height="740" :width="640"></Cropper>
</div>
<template #footer>
<span class="dialog-footer">
<el-button :icon="RefreshRight" type="info" @click="handleRotateRight"></el-button>
<el-button :icon="RefreshLeft" type="info" @click="handleRotateLeft"></el-button>
<el-button type="info" @click="closeCapture">關(guān)閉</el-button>
<el-button type="primary" @click="tailoring" :loading="cropperLoading">確定</el-button>
</span>
</template>
</el-dialog>
<script setup lang="ts">
const uploadRef = ref()
const showCaptureVisible = ref(false)
const cropper = ref()
// 上傳圖片loading
const { loading: cropperLoading } = useLoading()
// 裁剪圖片
const tailoring = async () => {
//文件大小
cropperLoading.value = true
const blob = await cropper.value.tailoring()
if (blob.size > 2 * 1024 * 1024) {
cropperLoading.value = false
warningMessage('圖片大小超出2M限制')
return
}
const formData = new FormData()
formData.append('file', blob, 'cropped.jpg')
formData.append('accountId', regionSelect.brandId as string)
uploadImage(formData) // 這里調(diào)用后臺(tái)api
.then(
async res => {
form.value.backgroundImage = res.data
doSuccess('上傳成功')
},
() => {
ElNotification({
type: 'warning',
message: '圖片上傳失敗'
})
}
)
.finally(() => {
formRef.value?.validate().catch(() => {})
// 關(guān)閉裁剪
showCaptureVisible.value = false
cropperLoading.value = false
})
}
// 圖片旋轉(zhuǎn)
const handleRotateLeft = () => {
cropper.value?.rotateLeft()
}
const handleRotateRight = () => {
cropper.value?.rotateRight()
}
// 上傳圖片
const handleCaptureUpload = (e: any) => {
const input = e.target as HTMLInputElement
if (!/\.(jpg|jpeg|png|JPG|PNG)$/.test(e.target.value)) {
warningMessage('圖片類型要求:jpeg、jpg、png')
return false
}
showCaptureVisible.value = true
nextTick(() => {
cropper.value?.selectImg(e)
input.value = ''
})
}
// 關(guān)閉裁剪
const closeCapture = () => {
showCaptureVisible.value = false
}
</script>三、實(shí)現(xiàn)效果
效果圖:


可進(jìn)行圖片旋轉(zhuǎn),裁剪 自定義裁剪的圖片大小
四、vue-cropper的全部參數(shù)

到此這篇關(guān)于Vue3結(jié)合vue-cropper實(shí)現(xiàn)圖片裁剪預(yù)覽功能的文章就介紹到這了,更多相關(guān)vue-cropper圖片裁剪預(yù)覽內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue3使用ref和reactive管理狀態(tài)的代碼示例
ref 和 reactive 是 Composition API 中用來聲明響應(yīng)式數(shù)據(jù)的兩個(gè)核心函數(shù),在 Vue 3 中,使用 setup 語法糖可以更簡潔地使用這些功能,本文將探討如何使用 ref 和 reactive 來管理狀態(tài),并解釋它們之間的區(qū)別,需要的朋友可以參考下2024-09-09
Vue.js實(shí)現(xiàn)大轉(zhuǎn)盤抽獎(jiǎng)總結(jié)及實(shí)現(xiàn)思路
這篇文章主要介紹了 Vue.js實(shí)現(xiàn)大轉(zhuǎn)盤抽獎(jiǎng)總結(jié)及實(shí)現(xiàn)思路,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-10-10
Vue記住滾動(dòng)條和實(shí)現(xiàn)下拉加載的完美方法
這篇文章主要給大家介紹了關(guān)于Vue記住滾動(dòng)條和實(shí)現(xiàn)下拉加載的完美方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
Vue全局自適應(yīng)大小:使用postcss-pxtorem方式
本文介紹了如何在Vue項(xiàng)目中使用postcss-pxtorem插件實(shí)現(xiàn)響應(yīng)式設(shè)計(jì),postcss-pxtorem可以自動(dòng)將CSS文件中的px單位轉(zhuǎn)換為rem單位,從而實(shí)現(xiàn)更好的自適應(yīng)布局,通過配置postcss-pxtorem插件,可以在構(gòu)建時(shí)自動(dòng)完成轉(zhuǎn)換,無需手動(dòng)修改代碼2025-01-01

