您现在的位置是:首页 > 编程语言学习 > 前端编程语言 > 文章正文 前端编程语言

vue3 el-upload+vue-cropper 实现头像裁剪上传

2022-12-14 11:57:23 前端编程语言

简介最近遇到一个头像裁剪上传需求,项目是vue3为框架的。大家先来看效果图吧! 以下以vue3为例第一步 vue-cropper的引入npminstallvue-cro...

最近遇到一个头像裁剪上传需求,项目是vue3为框架的。大家先来看效果图吧! 在这里插入图片描述 在这里插入图片描述

以下以vue3为例

第一步 vue-cropper的引入

  1. npm install vue-cropper@next 

页面组件中

  1. import 'vue-cropper/dist/index.css' 
  2. import { VueCropper }  from "vue-cropper"

第二步接下来直接上我封装的组件代码

***伙伴们拿着用

  1. <template> 
  2.   <el-dialog 
  3.     title="上传头像" 
  4.     v-model="dialogVisible" 
  5.     :show-close="false" 
  6.     :close-on-click-modal="false" 
  7.     :close-on-press-escape="false" 
  8.     destroy-on-close 
  9.     width="600px" 
  10.   > 
  11.     <div class="avatar-container"
  12.         <!-- {{dialogVisible}} --> 
  13.       <!-- 待上传图片 --> 
  14.       <div v-show="!options.img" > 
  15.         <el-upload 
  16.           class="upload" 
  17.           ref="elUpload" 
  18.           action="#" 
  19.           :on-change="upload" 
  20.           accept="image/png, image/jpeg, image/jpg" 
  21.           :show-file-list="false" 
  22.           :auto-upload="false" 
  23.         > 
  24.           <el-button slot="trigger"  type="primary" ref="uploadBtn"
  25.             选择图片 
  26.           </el-button> 
  27.         </el-upload> 
  28.         <div>支持jpg、png格式的图片,大小不超过5M</div> 
  29.       </div> 
  30.       <!-- <img :src="options.img" alt=""> --> 
  31.       <!-- 已上传图片 --> 
  32.       <div v-show="options.img" class="avatar-crop"
  33.         <vueCropper 
  34.           class="crop-box" 
  35.           ref="cropper" 
  36.           :img="options.img" 
  37.           :autoCrop="options.autoCrop" 
  38.           :fixedBox="options.fixedBox" 
  39.           :canMoveBox="options.canMoveBox" 
  40.           :autoCropWidth="options.autoCropWidth" 
  41.           :autoCropHeight="options.autoCropHeight" 
  42.           :centerBox="options.centerBox" 
  43.           :fixed="options.fixed" 
  44.           :fixedNumber="options.fixedNumber" 
  45.           :canMove="options.canMove" 
  46.           :canScale="options.canScale" 
  47.         ></vueCropper> 
  48.       </div> 
  49.     </div> 
  50.     <template #footer> 
  51.     <span  class="dialog-footer"
  52.       <div class="reupload" @click="reupload"
  53.         <span v-show="options.img">重新上传</span> 
  54.       </div> 
  55.       <div> 
  56.         <el-button @click="closeDialog">取 消</el-button> 
  57.         <el-button type="primary" @click="getCrop">确 定</el-button> 
  58.       </div> 
  59.     </span> 
  60.     </template> 
  61.   </el-dialog> 
  62. </template> 
  63.  
  64. <script lang="ts" > 
  65. import {ref,reactive,defineComponent} from "vue" 
  66. import { VueCropper } from 'vue-cropper' 
  67. import 'vue-cropper/dist/index.css' 
  68. import type { UploadProps, UploadUserFile } from 'element-plus' 
  69. import { 
  70.     ElMessage 
  71. } from 'element-plus' 
  72. export default defineComponent({ 
  73.   props: { 
  74.     dialogVisible: { 
  75.       type: Boolean, 
  76.     } 
  77.   }, 
  78.   components:{ 
  79.     VueCropper 
  80.   }, 
  81.   setup(props, { emit }) { 
  82.     // console.log(11111); 
  83.     const cropper=ref() 
  84.     const uploadBtn=ref() 
  85.     const elUpload=ref() 
  86.     const options=reactive({ 
  87.         img: ''// 原图文件 
  88.         autoCrop: true// 默认生成截图框 
  89.         fixedBox: false// 固定截图框大小 
  90.         canMoveBox: true// 截图框可以拖动 
  91.         autoCropWidth: 200, // 截图框宽度 
  92.         autoCropHeight: 200, // 截图框高度 
  93.         fixed: true// 截图框宽高固定比例 
  94.         fixedNumber: [1, 1], // 截图框的宽高比例 
  95.         centerBox: true// 截图框被限制在图片里面 
  96.         canMove: false// 上传图片不允许拖动 
  97.         canScale: false // 上传图片不允许滚轮缩放 
  98.       }) 
  99.       // vueCropper组件 裁剪配置信息 
  100.      
  101.  
  102.     // 读取原图 
  103.     const upload: UploadProps['onChange'] = (file, uploadFiles) => { 
  104.         console.log(file); 
  105.          
  106.       const isIMAGE = file.raw.type === 'image/jpeg' || file.raw.type === 'image/png' 
  107.       const isLt5M = file.raw.size / 1024 / 1024 < 5 
  108.       if (!isIMAGE) { 
  109.          ElMessage.warning("请选择 jpg、png 格式的图片" ); 
  110.         return false 
  111.       } 
  112.       if (!isLt5M) { 
  113.         ElMessage.warning("图片大小不能超过 5MB" ); 
  114.         return false 
  115.       } 
  116.       let reader = new FileReader() 
  117.        
  118.       reader.readAsDataURL(file.raw) 
  119.       console.log(reader); 
  120.        
  121.       reader.onload = e => { 
  122.         options.img = e.target.result // base64 
  123.         
  124.       } 
  125.       elUpload.value.clearFiles(); //这里处理重新上传时,upload组件change事件错误问题 
  126.     } 
  127.     // 获取截图信息 
  128.    const getCrop=()=> { 
  129.       // 获取截图的 base64 数据 
  130.       cropper.value.getCropData((data) => { 
  131.       //  console.log(data); 
  132.         
  133.       }); 
  134.       // 获取截图的 blob 数据 
  135.       console.log(cropper.value); 
  136.      cropper.value.getCropBlob(data => { 
  137.         // console.log(111); 
  138.          
  139.         console.log(data); 
  140.          
  141.         // emit('closeAvatarDialog') 
  142.         closeDialog() 
  143.       }) 
  144.     } 
  145.     // 重新上传 
  146.     const reupload=()=> { 
  147.          
  148.         // console.log(uploadBtn.value.ref); 
  149.          
  150.      uploadBtn.value.ref.click() 
  151.     } 
  152.     // 关闭弹框 
  153.    const closeDialog=()=> { 
  154.       emit('closeAvatarDialog'
  155.       options.img = '' 
  156.     } 
  157.  return { 
  158.          options, 
  159.          cropper, 
  160.          uploadBtn, 
  161.          elUpload, 
  162.          upload, 
  163.          getCrop, 
  164.         reupload, 
  165.         closeDialog 
  166.         } 
  167.   } 
  168. }) 
  169.  
  170.  
  171. </script> 
  172.  
  173. <style lang="scss" scoped> 
  174. .dialog-footer { 
  175.   display: flex; 
  176.   justify-content: space-between; 
  177.   align-items: center; 
  178.   font-size: 14px; 
  179.   .reupload { 
  180.     color: #409eff; 
  181.     cursor: pointer; 
  182.   } 
  183. .avatar-container { 
  184.   display: flex; 
  185.   justify-content: center; 
  186.   align-items: center; 
  187.   width: 560px; 
  188.   height: 350px; 
  189.   background-color: #f0f2f5; 
  190.   margin-right: 10px; 
  191.   border-radius: 4px; 
  192.   .upload { 
  193.     text-align: center; 
  194.     margin-bottom: 24px; 
  195.   } 
  196.   .avatar-crop { 
  197.     width: 560px; 
  198.     height: 350px; 
  199.     position: relative; 
  200.     .crop-box { 
  201.       width: 100%; 
  202.       height: 100%; 
  203.       border-radius: 4px; 
  204.       overflow: hidden; 
  205.     } 
  206.   } 
  207. </style> 

可以根据自己需要获取获取截图内容

获取截图的 base64 数据

  1. cropper.value.getCropData(data => { 
  2.   // do something 
  3.   console.log(data)   
  4. }) 
  5. 获取截图的 blob 数据 
  6.  
  7. cropper.value.getCropBlob(data => { 
  8.   // do something 
  9.   console.log(data)   
  10. }) 

第三步 使用封装得组件

  1. <template> 
  2.  
  3. <AvatarCropper v-if="dialogVisible" :dialogVisible.sync="dialogVisible" @closeAvatarDialog="closeAvatarDialog"></AvatarCropper> 
  4. //这里还是用了v-if来进行组件的销毁与创建,来解决一些不必要的问题 
  5. </template> 
  6.  
  7. <script lang="ts" setup> 
  8. import {ref,reactive,} from "vue"
  9. import AvatarCropper from '@/components/avatarCropper.vue' 
  10. const dialogVisible=ref(false
  11. const closeAvatarDialog=(data)=> { 
  12.         dialogVisible.value = false 
  13.       } 
  14. <script> 

好啦,以上就是分享内容。如果大家有遇到问题或更好的意见,欢迎大家的留言哦! 有帮助的话,点赞点赞点赞!!!

站点信息