效果图
上传图片弹窗预览
对于这个上传图片样式可以参考
官方原代码
官网传送入口 Upload 上传 | Element Plus (element-plus.org)
<template><el-uploadclass="upload-demo"dragaction="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"multiple><el-icon class="el-icon--upload"><upload-filled /></el-icon><div class="el-upload__text">Drop file here or <em>click to upload</em></div><template #tip><div class="el-upload__tip">jpg/png files with a size less than 500kb</div></template></el-upload>
</template><script setup lang="ts">
import { UploadFilled } from '@element-plus/icons-vue'
</script>
上传图片之后
裁剪图片之后
预览视频
裁剪图片预览视频
操作步骤
安装依赖
npm install cropperjs
npm i qs
npm i axios
npm i element-plus
template部分
<template><div><el-dialog :title="dialogTitle.imgTitle" width="800px" v-model="dialogVisible.imgCropperVisible" :before-close="handleBeforeClose"><div v-if="imageSrc" style="display: flex; justify-content: space-between; align-items: center;"><!-- Display cropped image or original image if not cropped with background --><div style="width: 50%; padding: 10px; background-color: #f5f5f5; display: flex; justify-content: center; align-items: center;"><img ref="previewImage" :src="croppedImageSrc || imageSrc" alt="Preview Image" style="max-width: 100%; height: auto;" /></div><!-- Upload image section without background --><div style="width: 50%; padding: 10px; display: flex; justify-content: center; align-items: center;"><img ref="uploadImage" :src="imageSrc" alt="Source Image" style="max-width: 100%; height: auto;" /></div></div><!-- Centered buttons --><div v-if="imageSrc" style="margin-top: 20px; text-align: center;"><el-button type="primary" @click="cropImage">裁剪图片</el-button><el-button @click="clearImage">重新选择</el-button><el-button type="primary" @click="uploadCroppedImage">上传头像</el-button></div><!-- Conditional display for upload component --><el-uploadv-if="!imageSrc"class="upload-demo"dragaction="http://localhost:8888/v1/file/singleUploadFile"multiplev-model:file-list="fileList"limit="1":show-file-list="false":before-upload="beforeUpload"><el-icon class="el-icon--upload"><upload-filled /></el-icon><div class="el-upload__text">Drop file here or <em>click to upload</em></div><template #tip><div class="el-upload__tip">jpg/png files with a size less than 500kb</div></template></el-upload></el-dialog></div><div><img :src="BASE_URL+attraction_detail.imageUrl" alt=""></div>
</template>
js部分
<script setup>
import { ref, nextTick, onBeforeUnmount } from 'vue';
import { ElMessage } from 'element-plus';
import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.css';
import axios from 'axios';const imageSrc = ref(null);
const croppedImageSrc = ref(null);
const dialogTitle = ref({ imgTitle: '上传图片' });
const dialogVisible = ref({ imgCropperVisible: true });
const fileList = ref([]);const uploadImage = ref(null);
const previewImage = ref(null);
let cropper = null;
const attraction_detail =ref({imageUrl:''})
const beforeUpload = (file) => {const isImage = file.type.startsWith('image/');if (!isImage) {ElMessage.error('只能上传图片文件');return false;}const reader = new FileReader();reader.onload = async (e) => {imageSrc.value = e.target.result;await nextTick();initCropper();};reader.readAsDataURL(file);return false;
};const initCropper = () => {if (cropper) {cropper.destroy();}if (!uploadImage.value) return;cropper = new Cropper(uploadImage.value, {aspectRatio: 1,viewMode: 1,});
};const cropImage = () => {if (cropper) {const canvas = cropper.getCroppedCanvas({width: 200,height: 200,});croppedImageSrc.value = canvas.toDataURL('image/png');}
};const clearImage = () => {imageSrc.value = null;croppedImageSrc.value = null;fileList.value = [];if (cropper) {cropper.destroy();cropper = null;}
};const uploadCroppedImage = async () => {if (!croppedImageSrc.value) {ElMessage.error('请先裁剪图片');return;}try {const blob = dataURLToBlob(croppedImageSrc.value);const formData = new FormData();formData.append('file', blob, 'avatar.png'); // 注意这里的表单字段名应为'file'const response = await axios.post('http://localhost:8888/v1/file/singleUploadFile', formData);if (response.data) {ElMessage.success('上传成功');dialogVisible.value.imgVisible = false;attraction_detail.value.imageUrl = response.data;console.log(response.data)console.log("")} else {ElMessage.error(response.data.msg || '上传失败');}} catch (error) {ElMessage.error('上传失败');}
};const dataURLToBlob = (dataURL) => {const arr = dataURL.split(',');const mime = arr[0].match(/:(.*?);/)[1];const bstr = atob(arr[1]);let n = bstr.length;const u8arr = new Uint8Array(n);while (n--) {u8arr[n] = bstr.charCodeAt(n);}return new Blob([u8arr], { type: mime });
};onBeforeUnmount(() => {if (cropper) {cropper.destroy();}
});
</script>
css部分
<style scoped>
.upload-demo .el-upload {display: block;width: 100%;margin-bottom: 20px;
}.el-upload__text {color: #606266;font-size: 14px;line-height: 22px;margin-top: 5px;
}.el-upload__tip {color: #909399;font-size: 12px;line-height: 1.5;margin-top: 7px;
}
</style>