赞
踩
官网地址:[GitHub - xyxiao001/vue-cropper: A simple picture clipping plugin for vue](https://github.com/xyxiao001/vue-cropper?from=thosefree.com)
下载插件
npm install vue-cropper@next
使用注意点
组件内引用-必须
import 'vue-cropper/dist/index.css'
import {VueCropper} from 'vue-cropper'
import {getCurrentInstance, ref, reactive, watch} from 'vue'
如下片段可自行更改,
const dp = defineProps({ // 接收父组件参数 realTime: "", // 实时时间 }) const de = defineEmits(["popUpClose"]) const avatarUpload = () => { // 图片上传事件 cropper.value.getCropBlob(data => { const formData = new FormData(); formData.append("id", sessionStorage.getItem("userid")); formData.append('mf',data); // file是你的文件对 axios.post('/person/uploadAvatar', formData) .then(response => { // 处理后台返回的结果 if(response.code !== 200) return ElMessage.error(response.msg) ElMessage.success(response.msg) de("popUpClose", response.data) }) .catch(error => { // 处理错误 ElMessage.error(error.message) throw error }); }) }
封装组件代码:
<template> <div class = "avatar-container" @click = ""> <el-row> <el-col :span = "12" style = "width: 600px; height: 300px"> <vue-cropper ref = "cropper" :img = "options.img" :info = "true" :autoCrop = "options.autoCrop" :autoCropWidth = "options.autoCropWidth" :autoCropHeight = "options.autoCropHeight" :fixedBox = "options.fixedBox" :outputType = "options.outputType" @realTime = "realTime" /> </el-col> <!-- 实时预览部分 --> <el-col :span = "12" style = "height: 300px"> <div class = "preview-box"> <img v-if = "previews.url" :src = "previews.url" :style="previews.img"/> <span v-else></span> </div> </el-col> </el-row> <el-row style = "margin-top: 12px"> <el-col :span = "12"> <el-row> <el-col :span = "8"> <el-upload action = "#" :http-request = "() => {}" :before-upload = "beforeUpload" :show-file-list = "false" > <el-button>选择</el-button> </el-upload> </el-col> <el-col :span = "4"> <el-button :icon = "Plus" @click = "changeScale(1)"></el-button> </el-col> <el-col :span = "4"> <el-button :icon = "Minus" @click = "changeScale(-1)"></el-button> </el-col> <el-col :span = "4"> <el-button :icon = "RefreshLeft" @click = "rotateLeft()"></el-button> </el-col> <el-col :span = "4"> <el-button :icon = "RefreshRight" @click = "rotateRight()"></el-button> </el-col> </el-row> </el-col> <el-col :span = "4" :offset = "8" style = "margin-left: 22.3%"> <el-button type = "primary" @click = "avatarUpload()">提 交</el-button> </el-col> </el-row> </div> </template> <script setup> import {Plus, Minus, RefreshLeft, RefreshRight} from '@element-plus/icons-vue' import {ElMessage} from 'element-plus' import 'vue-cropper/dist/index.css' import {VueCropper} from 'vue-cropper' import {getCurrentInstance, ref, reactive, watch} from 'vue' import axios from "axios"; const {proxy} = getCurrentInstance() const options = reactive({ img: "https://tse1-mm.cn.bing.net/th/id/OIP-C.rBx_awzG233bGXk-4h3eeAHaFL?w=262&h=184&c=7&r=0&o=5&dpr=1.3&pid=1.7", // 裁剪图片的地址 autoCropWidth: 200, // 默认生成截图框宽度 默认容器的 80% autoCropHeight: 200, // 默认生成截图框高度 默认容器的 80% outputType: 'png', // 裁剪生成图片的格式 jpeg, png, webp autoCrop: true, // 是否默认生成截图框 fixedBox: false // 固定截图框大小 }) let previews = ref({ url: '', img: '', }) // 修改图片大小 正数为变大 负数变小 const changeScale = (num) => { num = num || 1 proxy.$refs.cropper.changeScale(num) } // 向左边旋转90度 const rotateLeft = () => { proxy.$refs.cropper.rotateLeft() } // 向右边旋转90度 const rotateRight = () => { proxy.$refs.cropper.rotateRight() } // 上传图片处理 const beforeUpload = (rawFile) => { if (rawFile.type.indexOf('image/') == -1) { ElMessage.error('请上传图片类型文件!') return false } if (rawFile.size / 1024 / 1024 > 2) { ElMessage.error('文件大小不能超过2MB!') return false } const reader = new FileReader() reader.readAsDataURL(rawFile) reader.onload = () => { // 图片在这里 if (typeof reader.result === "string") { options.img = reader.result } } } // 实时预览事件 const realTime = (data) => { previews.value = data } const cropper = ref(null); const getBase64 = () => { // 获取截图的base64编码 cropper.value.getCropData(data => { console.log(data) }) } const getBlob = () => { // 获取截图的blob cropper.value.getCropBlob(data => { console.log(data) }) } const dp = defineProps({ // 接收父组件参数 realTime: "", // 实时时间 }) const de = defineEmits(["popUpClose"]) const avatarUpload = () => { // 图片上传事件 console.log(sessionStorage.getItem("userid")) cropper.value.getCropBlob(data => { const formData = new FormData(); formData.append("id", sessionStorage.getItem("userid")); formData.append('mf',data); // file是你的文件对 axios.post('/person/uploadAvatar', formData) .then(response => { // 处理后台返回的结果 if(response.code !== 200) return ElMessage.error(response.msg) ElMessage.success(response.msg) de("popUpClose", response.data) }) .catch(error => { // 处理错误 ElMessage.error(error.message) throw error }); }) } </script> <style lang = "scss" scoped> .avatar-container { .img-box { border-radius: 50%; border: 1px solid #ccc; width: 10vw; height: 10vw; } } .preview-box { position: absolute; top: 50%; transform: translate(50%, -50%); width: 200px; height: 200px; border-radius: 50%; border: 1px solid #ccc; overflow: hidden; } </style>
父组件代码 - 【可要可不要】
效果预览
注意点
<script setup> import {useRoute, useRouter} from 'vue-router'; import {onMounted, reactive, ref} from "vue"; import AvatarUpload from "./avatarUpload.vue"; const router = useRouter() const rt = reactive({ personDTO: {}, // 个人信息对象 show: false, realTime: '', // 实时时间 }) const popUpClose = (data) => { rt.show = false // 关闭 rt.personDTO.photo = data // 更新头像 } let showOverlay = ref(false) const upload = () => { // 用户头像上传 if(showOverlay) { console.log("uploading avatar") rt.show = true rt.realTime = new Date().getTime() } } </script> <template> <el-row :gutter = "20"> <el-col :span = "6"> <!-- 左卡片 --> <el-card> <div>个人信息</div> <el-divider/> <el-row type = "flex" justify = "center"> <div @mouseover = "showOverlay = true" @mouseleave = "showOverlay = false" @click = "upload()" style = "position: relative; cursor: pointer;"> <el-avatar :size = "120" :src = "`data:image/png;base64,${rt.personDTO.photo}`"/> <div v-if = "showOverlay" style = "position: absolute; border-radius:50%; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); display: flex; justify-content: center; align-items: center;"> <span style = "color: white; font-size: 24px;">+</span> </div> </div> </el-row> <!--弹出编辑--> <el-dialog v-model = "rt.show" style = "width:1000px; height: 800px"> <AvatarUpload @popUpClose = "popUpClose" :realTime = "rt.realTime"/> </el-dialog> <el-divider/> </el-card> </el-col> </el-row> </template> <style scoped> * { font-size: 12px; } .el-text-right { text-align: right; } </style>
EDN ! !!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。