vue3配合element plus实现头像裁剪
实现上传功能
首先添加vue3中写组件,使用element plus的el-upload实现上传功能
-
<el-upload class="upload-demo" drag style="width: 400px" :auto-upload="false"//关闭默认上传功能 :before-upload="beforeAvatarUpload"//检验图片大小和类型 :on-change="changeSize"//检测图片上传 > <el-icon class="el-icon--upload"><upload-filled /></el-icon> <div class="el-upload__text">请上传您的头像<em>上传</em></div> </el-upload> -
//导入el-upload----------- import { UploadFilled } from "@element-plus/icons-vue"; -
//实现检验图片大小和类型 import { reactive, ref } from "vue"; import { ElMessage } from "element-plus"; import axios from "axios"; const beforeAvatarUpload = (rawFile) => { if (!rawFile.type.includes("image")) { ElMessage.error("很抱歉您上传的不是图片格式"); return false; } else if (rawFile.size / 1024 / 1024 > 2) { ElMessage.error("您上传的图片大小超过了2MB"); return false; } return true; }; //检验图片上传 const changeSize = (UploadFile) => { //这里的UploadFile就是上传上去的文件 //图片上传以后出现dialog框,出现裁剪功能 }; -
<el-dialog v-model="centerDialogVisible" title="裁剪头像" width="60%" align-center > //centerDialogVisible是diakog是否出现 <!-- 这里可以来放图片 --> //这里就可以来放裁剪功能的代码 <template #footer> <span class="dialog-footer"> <el-button @click="centerDialogVisible = false">取消</el-button> <el-button type="primary" @click="uploadAvatar"> 确认 </el-button> </span> </template> </el-dialog> const centerDialogVisible = ref(false); const uploadFile = ref({}); -
引入vue-Cropper
//安装 npm install vue-cropper@next //引入 import 'vue-cropper/dist/index.css' import { VueCropper } from "vue-cropper"; -
使用vue-Cropper
<el-dialog v-model="centerDialogVisible" title="裁剪头像" width="60%" align-center > <!-- 这里可以来放图片 --> <vueCropper class="crop-box" ref="cropper" :img="option.img" :outputSize="option.size" :outputType="option.outputType" :info="true" :full="option.full" :canMove="option.canMove" :canMoveBox="option.canMoveBox" :original="option.original" :autoCrop="option.autoCrop" :fixed="option.fixed" :fixedNumber="option.fixedNumber" :centerBox="option.centerBox" :infoTrue="option.infoTrue" :fixedBox="option.fixedBox" :autoCropWidth="option.autoCropWidth" :autoCropHeight="option.autoCropHeight" @cropMoving="cropMoving" ></vueCropper> <template #footer> <span class="dialog-footer"> <el-button @click="centerDialogVisible = false">取消</el-button> <el-button type="primary" @click="uploadAvatar"> 确认 </el-button> </span> </template> </el-dialog> <script setup> import { UploadFilled } from "@element-plus/icons-vue"; import { ElMessage } from "element-plus"; import { reactive, ref } from "vue"; import "vue-cropper/dist/index.css"; import { VueCropper } from "vue-cropper"; import axios from "axios"; const centerDialogVisible = ref(false); const croppedImageData = ref(null); //获取裁剪图片组件 const cropper = ref(); const imageSrc = ref(""); const option = reactive({ img: "", // 裁剪图片的地址 info: true, // 裁剪框的大小信息 outputSize: 1, // 裁剪生成图片的质量 outputType: "jpg", // 裁剪生成图片的格式 canScale: true, // 图片是否允许滚轮缩放 autoCrop: true, // 是否默认生成截图框 canMoveBox: true, // 截图框能否拖动 autoCropWidth: 200, // 默认生成截图框宽度 autoCropHeight: 200, // 默认生成截图框高度 fixedBox: false, // 固定截图框大小 不允许改变 fixed: true, // 是否开启截图框宽高固定比例 fixedNumber: [1, 1], // 截图框的宽高比例 full: false, // 是否输出原图比例的截图 original: false, // 上传图片按照原始比例渲染 centerBox: false, // 截图框是否被限制在图片里面 infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高 }); const beforeAvatarUpload = (rawFile) => { if (!rawFile.type.includes("image")) { //判断是否是图片格式 ElMessage.error("很抱歉您上传的不是图片格式"); return false; //验证图片大小 } else if (rawFile.size / 1024 / 1024 > 2) { ElMessage.error("您上传的图片大小超过了2MB"); return false; } return true; }; const changeSize = (UploadFile) => { centerDialogVisible.value = true; //这里将图片转化为base64位格式为图片进行裁剪 const reader = new FileReader(); reader.onload = (e) => { //将图片绑定到裁剪组件的img中 option.img = e.target.result; }; //拿到图片的base64 reader.readAsDataURL(UploadFile.raw); }; //上传头像点击了确认按钮 const uploadAvatar = () => { //上传头像并且点击了确认按钮 cropper.value.getCropBlob(async (data) => { // do something let formData = new FormData(); //第三个参数是规定以什么为后缀,接口是根据后缀来返回地址格式的 formData.append("file", data, "avatar.jpg"); //上传文件接口 let res = await axios({ method: "post", //请求地址 url: "http://localhost:3000/api/upload/image", data: formData, headers: { "Content-Type": "multipart/form-data", // Use 'multipart/form-data' for file uploads }, }); if (res.status == 200) { imageSrc.value = res.data.data.path; ElMessage({ message: "恭喜您上传头像成功", type: "success", }); centerDialogVisible.value = false; } }); }; </script> <style lang="scss" scoped> .dialog-footer button:first-child { margin-right: 10px; } :deep(.el-dialog__body) { width: 97%; height: 600px; } </style> -
功能所有代码
<template> <div style=" width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; " > <img :src="imageSrc" alt="" /> <el-upload class="upload-demo" drag style="width: 400px" :auto-upload="false" :before-upload="beforeAvatarUpload" :on-change="changeSize" > <el-icon class="el-icon--upload"><upload-filled /></el-icon> <div class="el-upload__text">请上传您的头像<em>上传</em></div> </el-upload> <el-dialog v-model="centerDialogVisible" title="裁剪头像" width="60%" align-center > <!-- 这里可以来放图片 --> <vueCropper class="crop-box" ref="cropper" :img="option.img" :outputSize="option.size" :outputType="option.outputType" :info="true" :full="option.full" :canMove="option.canMove" :canMoveBox="option.canMoveBox" :original="option.original" :autoCrop="option.autoCrop" :fixed="option.fixed" :fixedNumber="option.fixedNumber" :centerBox="option.centerBox" :infoTrue="option.infoTrue" :fixedBox="option.fixedBox" :autoCropWidth="option.autoCropWidth" :autoCropHeight="option.autoCropHeight" @cropMoving="cropMoving" ></vueCropper> <template #footer> <span class="dialog-footer"> <el-button @click="centerDialogVisible = false">取消</el-button> <el-button type="primary" @click="uploadAvatar"> 确认 </el-button> </span> </template> </el-dialog> </div> </template> <script setup> import { UploadFilled } from "@element-plus/icons-vue"; import { ElMessage } from "element-plus"; import { reactive, ref } from "vue"; import "vue-cropper/dist/index.css"; import { VueCropper } from "vue-cropper"; import axios from "axios"; const centerDialogVisible = ref(false); const uploadFile = ref({}); const croppedImageData = ref(null); const cropper = ref(); const imageSrc = ref(""); const option = reactive({ img: "", // 裁剪图片的地址 info: true, // 裁剪框的大小信息 outputSize: 1, // 裁剪生成图片的质量 outputType: "jpg", // 裁剪生成图片的格式 canScale: true, // 图片是否允许滚轮缩放 autoCrop: true, // 是否默认生成截图框 canMoveBox: true, // 截图框能否拖动 autoCropWidth: 200, // 默认生成截图框宽度 autoCropHeight: 200, // 默认生成截图框高度 fixedBox: false, // 固定截图框大小 不允许改变 fixed: true, // 是否开启截图框宽高固定比例 fixedNumber: [1, 1], // 截图框的宽高比例 full: false, // 是否输出原图比例的截图 original: false, // 上传图片按照原始比例渲染 centerBox: false, // 截图框是否被限制在图片里面 infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高 }); const beforeAvatarUpload = (rawFile) => { if (!rawFile.type.includes("image")) { ElMessage.error("很抱歉您上传的不是图片格式"); return false; } else if (rawFile.size / 1024 / 1024 > 2) { ElMessage.error("您上传的图片大小超过了2MB"); return false; } return true; }; const changeSize = (UploadFile) => { centerDialogVisible.value = true; uploadFile.value = UploadFile; const reader = new FileReader(); reader.onload = (e) => { option.img = e.target.result; }; reader.readAsDataURL(UploadFile.raw); }; const uploadAvatar = () => { //上传头像并且点击了确认按钮 cropper.value.getCropBlob(async (data) => { // do something let formData = new FormData(); //第三个参数是规定以什么为后缀,接口是根据后缀来返回地址格式的 formData.append("file", data, "avatar.jpg"); //上传文件接口 let res = await axios({ method: "post", url: "http://localhost:3000/api/upload/image", data: formData, headers: { "Content-Type": "multipart/form-data", // Use 'multipart/form-data' for file uploads }, }); if (res.status == 200) { imageSrc.value = res.data.data.path; ElMessage({ message: "恭喜您上传头像成功", type: "success", }); centerDialogVisible.value = false; } }); //let formData = new FormData(); //formData.append("file", uploadFile.value.raw); //在这个里面就可以拿到图片的具体参数 //centerDialogVisible.value = false; }; </script> <style lang="scss" scoped> .dialog-footer button:first-child { margin-right: 10px; } :deep(.el-dialog__body) { width: 97%; height: 600px; } </style>