vue3+ElementPlus+VueCropper實(shí)現(xiàn)上傳圖片功能
前言
我們需要上傳圖片,然后彈框進(jìn)行裁剪(放大、縮小)。
效果
實(shí)現(xiàn)
裁剪組件.vue
<template> <div> <!--裁剪圖片--> <el-dialog v-model="tailorDialogVisible" @open="onTailorDialogOpen" @close="onTailorDialogCancel" title="編輯圖片" width="680" align-center> <div style=" width: 550px; height: 450px; margin: 30px auto;" v-loading="loading" element-loading-text="Loading..."> <vue-cropper ref="cropper" :img="tailorOption.img" :output-type="tailorOption.outputType" :full="tailorOption.full" :auto-crop="tailorOption.autoCrop" :auto-crop-width="tailorOption.autoCropWidth" :auto-crop-height="tailorOption.autoCropHeight" :center-box="tailorOption.centerBox" :max-img-size="tailorOption.max" mode="cover" @imgLoad="onTailorLoad" ></vue-cropper> </div> <div style="display: flex; margin: 0 200px; justify-content: center; align-items: center"> <div style="width: 40px;text-align: left; cursor: pointer;"> <!-- <el-icon @click="onScaleMinus(0.1)" :size="16"><Minus /></el-icon> --> <span @click="onScaleMinus(0.1)">-號</span> </div> <div style="flex: 1"> <el-slider v-model="tailorAmplificationValue" :min="1" :max="3" :step="0.1" @change="onChangTailorAmplificationSlider" /> </div> <div style="width: 40px;text-align: right; cursor: pointer;"> <!-- <el-icon @click="onScaleAdd(0.1)" :size="16"><Plus /></el-icon> --> <span @click="onScaleAdd(0.1)">+號</span> </div> </div> <div style="display: flex; margin: 10px 200px 40px 200px; justify-content: center; align-items: center"> <div style="width: 40px;text-align: left; cursor: pointer;"> <span @click="onRotateLeft">左旋</span> <!-- <el-icon @click="onRotateLeft" :size="16"><Plus /></el-icon> --> <!-- <img @click="onRotateLeft" style="width: 14px; height: 14px" src="../../../public/img/recipeManage/left_rotate.png" alt=""> --> </div> <div style="flex: 1"> <el-slider v-model="tailorSpinValue" :min="-180" :max="180" :step="90" @change="onChangTailorSpinSlider" /> </div> <div style="width: 40px;text-align: right; cursor: pointer;"> <span @click="onRotateRight">右旋</span> <!-- <el-icon @click="onRotateRight" :size="16"><Plus /></el-icon> --> <!-- <img @click="onRotateRight" style="width: 14px; height: 14px" src="../../../public/img/recipeManage/right_rotate.png" alt=""> --> </div> </div> <div style="padding-top: 20px;" class="recipeManage_border_top"> <div style="display: flex; align-items: center; justify-content: center"> <div> <el-button type="primary" plain @click="onTailorDialogCancel">取消</el-button> </div> <div style="margin-left: 20px"> <el-button type="primary" @click="onTailorDialogSubmit">確認(rèn)</el-button> </div> </div> </div> </el-dialog> </div> </template> <script setup> import 'vue-cropper/dist/index.css' import { VueCropper } from "vue-cropper"; // import { postImgData } from '@/api/base/public'; import { ref, defineProps, toRefs, defineEmits } from 'vue'; const emit = defineEmits(['close', 'submit']); const props = defineProps({ tailorDialogImg: { default: '' }, autoCropWidth: { default: 180 }, autoCropHeight: { default: 180 }, tailorDialogVisible: { type: Boolean, required: true, default: false }, }); const { tailorDialogVisible, tailorDialogImg, autoCropWidth, autoCropHeight } = toRefs(props); const loading = ref(false); // 裁剪圖片 const cropper = ref(""); // const tailorDialogVisible = ref(visible.value); const tailorAmplificationValue = ref(0); const tailorSpinValue = ref(0); const tailorOption = ref({ img: "", full: false, outputType: 'png', autoCrop: true, autoCropWidth: 180, autoCropHeight: 180, centerBox: true, max: 99999, }); // 放大 let oldTailorAmplificationValue = 0; const onScaleAdd = (num) => { if (tailorAmplificationValue.value === 3) return; // tailorAmplificationValue.value = Number(parseFloat(tailorAmplificationValue.value + num).toFixed(1)); tailorAmplificationValue.value = +(parseFloat(tailorAmplificationValue.value + num).toFixed(1)); oldTailorAmplificationValue = tailorAmplificationValue.value; cropper.value.changeScale(tailorAmplificationValue.value); }; const onScaleMinus = (num) => { if (tailorAmplificationValue.value === 1) return; tailorAmplificationValue.value = tailorAmplificationValue.value - num; oldTailorAmplificationValue = -tailorAmplificationValue.value; cropper.value.changeScale(-tailorAmplificationValue.value); }; const onChangTailorAmplificationSlider = (value) => { if (oldTailorAmplificationValue > value) { cropper.value.changeScale(-value); } else { cropper.value.changeScale(value); } oldTailorAmplificationValue = value; }; // 旋轉(zhuǎn) let oldTailorRotateValue = 0; const onChangTailorSpinSlider = (value) => { if (value > 0) { cropper.value.rotateRight(); } else { cropper.value.rotateLeft(); } }; const onRotateLeft = () => { if (cropper.value.rotate === -2) return false; cropper.value.rotateLeft(); oldTailorRotateValue = cropper.value.rotate * 90 console.log("===oldTailorRotateValue===", oldTailorRotateValue) tailorSpinValue.value = cropper.value.rotate * 90 }; const onRotateRight = () => { if (cropper.value.rotate === 2) return false; cropper.value.rotateRight(); oldTailorRotateValue = cropper.value.rotate * 90 console.log("===oldTailorRotateValue===", oldTailorRotateValue) tailorSpinValue.value = cropper.value.rotate * 90 }; const onTailorDialogOpen = () => { console.log("===彈框打開==="); loading.value = true; tailorOption.value.img = tailorDialogImg.value; tailorOption.value.autoCropWidth = autoCropWidth.value; tailorOption.value.autoCropHeight = autoCropHeight.value; }; const onTailorLoad = (msg) => { console.log("===msg===", msg) loading.value = false; }; const onTailorDialogCancel = () => { emit('close'); loading.value = false; tailorOption.value.img = ""; tailorAmplificationValue.value = 0; tailorSpinValue.value = 0; }; const onTailorDialogSubmit = () => { cropper.value.getCropData(data => { tailorAmplificationValue.value = 0; tailorSpinValue.value = 0; tailorOption.value.img = ""; emit('submit', data); }) // cropper.value.getCropBlob(data => { // // 創(chuàng)建 FormData 對象并添加 Blob 對象 // const formData = new FormData(); // formData.append('file', data, '1.png'); // // postImgData(formData).then((res) => { // // if (res.data.code === 200) { // // emit('submit', res.data.data); // // } // // }).catch(err => {}); // tailorAmplificationValue.value = 0; // tailorSpinValue.value = 0; // tailorOption.value.img = ""; // emit('submit', ''); // }) // let blob = await cropper.value.getCropBlob(); // // 創(chuàng)建 FormData 對象并添加 Blob 對象 // const formData = new FormData(); // formData.append('file', blob, '1.png'); // let res = postImgData(formData); // // emit('submit', res.data.data); // // tailorAmplificationValue.value = 0; // tailorSpinValue.value = 0; // tailorOption.value.img = ""; }; </script> <style> </style>
使用組件.vue
<template> <div> <el-upload action="#" :http-request="onImgRequest" :show-file-list="false" :before-upload="(file) => onImgUpload(file)"> <div style="height: 100px; width: 100px; background-color: red;">上傳</div> </el-upload> <el-image v-if="imagesUrl" :src="imagesUrl"></el-image> <tailorImage :tailorDialogVisible="tailorDialogVisible" :tailorDialogImg="tailorDialogImg" @submit="tailorDialogImgSucc"></tailorImage> <!-- <el-image :src="src" /> --> </div> </template> <script setup> import tailorImage from "./components/TailorImage.vue" import {ref} from "vue" import { ElMessage } from 'element-plus'; const tailorDialogVisible = ref(false) const tailorDialogImg = ref("") const imagesUrl = ref("") const onImgRequest = () => {}; const onImgUpload = (rawFile) => { if (rawFile.type.indexOf('image/') === -1) { ElMessage.error('文件格式錯誤,請上傳圖片類型,如: JPG,PNG后綴的文件'); return false; } else { const reader = new FileReader(); reader.readAsDataURL(rawFile); reader.onload = () => { tailorDialogImg.value = reader.result; tailorDialogVisible.value = true; }; } }; const tailorDialogImgSucc = (data) => { // console.log("===tailorDialogImgSucc===", data) imagesUrl.value = data; tailorDialogVisible.value = false; tailorDialogImg.value = ""; } // const test = () => { // tailorDialogVisible.value = true // console.log("===裁剪圖片===="); // } </script> <style> </style>
到此這篇關(guān)于vue3+ElementPlus+VueCropper實(shí)現(xiàn)上傳圖片的文章就介紹到這了,更多相關(guān)vue3 ElementPlus VueCropper上傳圖片內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue項(xiàng)目中使用rimraf?dev啟動時刪除dist目錄方式
這篇文章主要介紹了vue項(xiàng)目中使用rimraf?dev啟動時刪除dist目錄方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04vue3配置代理實(shí)現(xiàn)axios請求本地接口返回PG庫數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了vue3配置代理實(shí)現(xiàn)axios請求本地接口返回PG庫數(shù)據(jù)的相關(guān)知識,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2025-03-03Vue使用Element實(shí)現(xiàn)增刪改查+打包的步驟
這篇文章主要介紹了Vue使用Element實(shí)現(xiàn)增刪改查+打包的步驟,幫助大家更好的理解和學(xué)習(xí)vue框架,感興趣的朋友可以了解下2020-11-11vue用Object.defineProperty手寫一個簡單的雙向綁定的示例
這篇文章主要介紹了用Object.defineProperty手寫一個簡單的雙向綁定的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-07-07使用Vue調(diào)取接口,并渲染數(shù)據(jù)的示例代碼
今天小編就為大家分享一篇使用Vue調(diào)取接口,并渲染數(shù)據(jù)的示例代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-10-10vue項(xiàng)目展示pdf文件的方法實(shí)現(xiàn)
本文主要介紹了vue項(xiàng)目展示pdf文件的方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07rem實(shí)現(xiàn)響應(yīng)式布局的思路詳解
這篇文章主要為大家介紹了rem實(shí)現(xiàn)響應(yīng)式布局的思路詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03