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

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

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

以下以vue3为例

第一步 vue-cropper的引入

npm install vue-cropper@next

页面组件中

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

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

***伙伴们拿着用

<template>
  <el-dialog
    title="上传头像"
    v-model="dialogVisible"
    :show-close="false"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    destroy-on-close
    width="600px"
  >
    <div class="avatar-container">
        <!-- {{dialogVisible}} -->
      <!-- 待上传图片 -->
      <div v-show="!options.img" >
        <el-upload
          class="upload"
          ref="elUpload"
          action="#"
          :on-change="upload"
          accept="image/png, image/jpeg, image/jpg"
          :show-file-list="false"
          :auto-upload="false"
        >
          <el-button slot="trigger"  type="primary" ref="uploadBtn">
            选择图片
          </el-button>
        </el-upload>
        <div>支持jpg、png格式的图片,大小不超过5M</div>
      </div>
      <!-- <img :src="options.img" alt=""> -->
      <!-- 已上传图片 -->
      <div v-show="options.img" class="avatar-crop">
        <vueCropper
          class="crop-box"
          ref="cropper"
          :img="options.img"
          :autoCrop="options.autoCrop"
          :fixedBox="options.fixedBox"
          :canMoveBox="options.canMoveBox"
          :autoCropWidth="options.autoCropWidth"
          :autoCropHeight="options.autoCropHeight"
          :centerBox="options.centerBox"
          :fixed="options.fixed"
          :fixedNumber="options.fixedNumber"
          :canMove="options.canMove"
          :canScale="options.canScale"
        ></vueCropper>
      </div>
    </div>
    <template #footer>
    <span  class="dialog-footer">
      <div class="reupload" @click="reupload">
        <span v-show="options.img">重新上传</span>
      </div>
      <div>
        <el-button @click="closeDialog">取 消</el-button>
        <el-button type="primary" @click="getCrop">确 定</el-button>
      </div>
    </span>
    </template>
  </el-dialog>
</template>

<script lang="ts" >
import {ref,reactive,defineComponent} from "vue"
import { VueCropper } from 'vue-cropper'
import 'vue-cropper/dist/index.css'
import type { UploadProps, UploadUserFile } from 'element-plus'
import {
    ElMessage
} from 'element-plus'
export default defineComponent({
  props: {
    dialogVisible: {
      type: Boolean,
    }
  },
  components:{
    VueCropper
  },
  setup(props, { emit }) {
    // console.log(11111);
    const cropper=ref()
    const uploadBtn=ref()
    const elUpload=ref()
    const options=reactive({
        img: '', // 原图文件
        autoCrop: true, // 默认生成截图框
        fixedBox: false, // 固定截图框大小
        canMoveBox: true, // 截图框可以拖动
        autoCropWidth: 200, // 截图框宽度
        autoCropHeight: 200, // 截图框高度
        fixed: true, // 截图框宽高固定比例
        fixedNumber: [1, 1], // 截图框的宽高比例
        centerBox: true, // 截图框被限制在图片里面
        canMove: false, // 上传图片不允许拖动
        canScale: false // 上传图片不允许滚轮缩放
      })
      // vueCropper组件 裁剪配置信息
    

    // 读取原图
    const upload: UploadProps['onChange'] = (file, uploadFiles) => {
        //console.log(file);
        
      const isIMAGE = file.raw.type === 'image/jpeg' || file.raw.type === 'image/png'
      const isLt5M = file.raw.size / 1024 / 1024 < 5
      if (!isIMAGE) {
         ElMessage.warning("请选择 jpg、png 格式的图片" );
        return false
      }
      if (!isLt5M) {
        ElMessage.warning("图片大小不能超过 5MB" );
        return false
      }
      let reader = new FileReader()
      
      reader.readAsDataURL(file.raw)
      //console.log(reader);
      
      reader.onload = e => {
        options.img = e.target.result // base64
       
      }
      elUpload.value.clearFiles(); //这里处理重新上传时,upload组件change事件错误问题
    }
    // 获取截图信息
   const getCrop=()=> {
      // 获取截图的 base64 数据
      cropper.value.getCropData((data) => {
      //  console.log(data);
       
      });
      // 获取截图的 blob 数据
      //console.log(cropper.value);
     cropper.value.getCropBlob(data => {
        // console.log(111);
         let formData = new FormData();
         //第三个参数是规定以什么为后缀,接口是根据后缀来返回地址格式的
              formData.append("file", data,'chris.jpg');
              //上传接口
              uploadApi(formData).then(res=>{
              
              })
        //console.log(data);
        
        // emit('closeAvatarDialog')
        closeDialog()
      })
    }
    // 重新上传
    const reupload=()=> {
        
        // console.log(uploadBtn.value.ref);
        
     uploadBtn.value.ref.click()
    }
    // 关闭弹框
   const closeDialog=()=> {
      emit('closeAvatarDialog')
      options.img = ''
    }
 return {
         options,
         cropper,
         uploadBtn,
         elUpload,
         upload,
         getCrop,
        reupload,
        closeDialog
        }
  }
})


</script>

<style lang="scss" scoped>
.dialog-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 14px;
  .reupload {
    color: #409eff;
    cursor: pointer;
  }
}
.avatar-container {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 560px;
  height: 350px;
  background-color: #f0f2f5;
  margin-right: 10px;
  border-radius: 4px;
  .upload {
    text-align: center;
    margin-bottom: 24px;
  }
  .avatar-crop {
    width: 560px;
    height: 350px;
    position: relative;
    .crop-box {
      width: 100%;
      height: 100%;
      border-radius: 4px;
      overflow: hidden;
    }
  }
}
</style>

可以根据自己需要获取获取截图内容(这里以bolb为例,转为formdata格式传给后端)

获取截图的 base64 数据

cropper.value.getCropData(data => {
  // do something
  //console.log(data)  
})

获取截图的 blob 数据

cropper.value.getCropBlob(data => {
  // do something
  let formData = new FormData();
    //第三个参数是规定以什么为后缀,接口是根据后缀来返回地址格式的
    formData.append("file", data,'chris.jpg');
      //上传文件接口
    uploadApi(formData).then(res=>{
              
              })
  //console.log(data)  
})

第三步 使用封装得组件

<template>
//这里是头像
<div class="userPhoto " @click="dialogVisible=true">
	<img src="@/assets/images/defaultHeard.png" alt=""/>
</div>
<AvatarCropper v-if="dialogVisible" :dialogVisible.sync="dialogVisible" @closeAvatarDialog="closeAvatarDialog"></AvatarCropper>
//这里还是用了v-if来进行组件的销毁与创建,来解决一些不必要的问题
</template>

<script lang="ts" setup>
import {ref,reactive,} from "vue";
import AvatarCropper from '@/components/avatarCropper.vue'
const dialogVisible=ref(false)
// 关闭弹框所触发的事件
const closeAvatarDialog=(data)=> {
        dialogVisible.value = false
      }
<script>

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

  • 7
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Vue中,你可以结合`element-ui`的`el-upload`组件和`vue-cropper`库来实现图片上传裁剪功能。以下是一个基本的步骤: 1. 安装依赖: 首先,你需要安装这两个库,如果你还没有安装,可以在项目目录下运行: ```bash npm install element-ui vue-cropper ``` 2. 引入组件: 在你的Vue文件中,引入这两个组件: ```javascript import { ElUpload } from 'element-ui'; import VueCropper from 'vue-cropper'; ``` 3. 在模板中使用`el-upload`和`vue-cropper`: ```html <template> <div> <el-upload :action="uploadUrl" :on-success="handleSuccess" :on-change="handleChange" :before-upload="beforeUpload" ref="upload" > <el-button size="small" type="primary">点击选择图片</el-button> </el-upload> <vue-cropper ref="cropper" :img-url="croppedImageUrl" :output-type="outputType"></vue-cropper> </div> </template> ``` 4. 编写方法: - `handleSuccess(response, file)`:处理上传成功后的回调,这里可以更新`croppedImageUrl`。 - `handleChange(file)`:处理文件变化,可以预览图片并显示到cropper组件中。 - `beforeUpload(file)`:在上传前的钩子,可以在这里做些验证或处理。 5. 数据绑定: ```javascript data() { return { uploadUrl: 'your-upload-url', croppedImageUrl: '', outputType: 'image/jpeg', // 可选类型:image/jpeg, image/png, image/webp }; }, methods: { handleSuccess(response, file) { // 在这里处理上传成功的响应并更新croppedImageUrl this.croppedImageUrl = response.data.url; }, handleChange(file) { this.$refs.upload.fileList = file; // 将文件信息传递给cropper this.$refs.cropper.src = file.url; // 设置cropper的图片源 }, beforeUpload(file) { // 这里可以根据需求检查文件大小、类型等 } } ``` 注意替换`your-upload-url`为你实际的图片上传地址。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一行代码上晴天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值