AntDesign upload 修改头像

在我们的项目中,往往会遇到要将图片进行裁剪/或者缩放后在进行上传使用,最近做了一个修改头像的功能,需要缩放,裁剪等功能。

  点击修改头像

 

 修改头像组件:  Ant Design   Ant Design Vue  (upload 官方文档)

功能需求:1点击头像,显示修改头像的弹框,回显当前头像图片。2.可剪裁图片/放大或者缩小/旋转等。3.点击确定,头像上传成功,回显修改后的头像。

具体思路:1.上传之前,校验图片的格式和大小,点击保存的时候。处理数据,调用接口,回显图                   片。2.剪裁和旋转缩放,采用的是vue-cropper 插件  官网:                https://gitee.com/yxl-qwe/vue-cropper

上代码

父组件

<avatar-modal ref="modal" @ok="setavatar" v-if="visible" :visible="visible" @cancelAvatar="cancelAvatar" :imgs="img"
      @okFinish="okFinish" />
<script>
import AvatarModal from '../settings/AvatarModal.vue'
import { updateAvatar, uploadImg } from '@/api/login'
import { mapActions } from 'vuex'

data() {
    return {
      visible: false,
      id: null,
      img:'',
}

methods: {
    ...mapActions({
      getInfo: 'GetInfo'
    }),

    //修改头像
    handelAvatar(id) {
      this.visible = true
      this.id = id
    },
    cancelAvatar() {
      console.log('关闭');
      this.visible = false
      this.id = null
    },

    okFinish(type, f) {
      // 上传图片(点击上传按钮)
      // const _this = this
      let file = f
      const formData = new FormData()
      // 输出
      if (f) {
        this.$refs.modal.$refs.cropper.getCropBlob((data) => {
          const time = new Date().getTime();
          const fileName = time + "_" + file.name;
          // blob转file
          let trueFile = new window.File([data], fileName, {
            type: data.type,
          });
          formData.append('file', trueFile)
          uploadImg(formData).then(res => {
            if (res.code === 2000) {
              this.visible = false
              this.img = res.data.url
              const avatar = {
                avatar: res.data.url
              }
              updateAvatar(avatar).then(res => {
                if (res.code === 2000) {
                  //提示用户更新成功
                  this.$message.info(res.message)
                  this.getInfo()
                  this.img=''
                }
              })
            }
          })
        })
      }else{
        this.visible = false
        // this.img=''
      }
    },
}
</script>

子组件

<template>
  <a-modal title="修改头像" :visible="visible"  :confirmLoading="confirmLoading" :width="800"  
     :maskClosable="false"  @cancel="() => { $emit('cancelAvatar') }"  @ok="() => { $emit('okFinish', 'blob',file) }">
    <a-form :preserve='false'>
      <a-row>
        <a-col :xs="24" :md="12" :style="{ height: '350px' }">
          <vue-cropper ref="cropper" :img="options.img" :info="true" :autoCrop="options.autoCrop"
            :autoCropWidth="options.autoCropWidth" :autoCropHeight="options.autoCropHeight" :fixedBox="options.fixedBox"
            @realTime="realTime">
          </vue-cropper>
        </a-col>
        <a-col :xs="24" :md="12" :style="{ height: '350px' }">
          <div class="avatar-upload-preview">
            <img :src="previews.url" :style="previews.img" />
          </div>
        </a-col>
      </a-row>
      <br>
      <a-row>
        <a-col :lg="2" :md="2">
          <a-upload name="file" :beforeUpload="beforeUpload" :showUploadList="false">
            <a-button icon="upload">选择图片</a-button>
          </a-upload>
        </a-col>
        <span>
          <a-col :lg="{ span: 1, offset: 2 }" :md="2">
          <a-button icon="plus" @click="changeScale(1)" />
        </a-col>
        <a-col :lg="{ span: 1, offset: 1 }" :md="2">
          <a-button icon="minus" @click="changeScale(-1)" />
        </a-col>
        <a-col :lg="{ span: 1, offset: 1 }" :md="2">
          <a-button icon="undo" @click="rotateLeft" />
        </a-col>
        <a-col :lg="{ span: 1, offset: 1 }" :md="2">
          <a-button icon="redo" @click="rotateRight" />
        </a-col>
        </span>
        
      </a-row>
    </a-form>

  </a-modal>
</template>

 

<script>

export default {
  props: {
    visible: {
      type: Boolean,
      default:false,
    },
    imgs:{
      type:String,
      default:''
    }
  },
  data() {
    return {
      file: null,
      id: null,
      confirmLoading: false,
      uploading: false,
      options: {
        img: this.imgs,
        autoCrop: true,
        autoCropWidth: 200,
        autoCropHeight: 200,
        fixedBox: true
      },
      previews: {
        url: this.$store.getters.userInfo.avatar,
      },
      isFirst:true,
      isShow:false,
    }
  },
  methods: {
    changeScale(num) {
      if(this.options.img ==''){
        return
      }
      num = num || 1
      this.$refs.cropper.changeScale(num)
    },
    rotateLeft() {
      if(this.options.img ==''){
        return
      }
      this.$refs.cropper.rotateLeft()
    },
    rotateRight() {
      if(this.options.img ==''){
        return
      }
      this.$refs.cropper.rotateRight()
    },
    beforeUpload(file) {
      const isJpgOrPng =
        file.type === "image/jpeg" ||
        file.type === "image/jpg" ||
        file.type === "image/png";
      if (!isJpgOrPng) {
        this.$message.error(`只能上传jpeg/jpg/png格式的图片`);
        return
      }
      const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isLt2M) {
        this.$message.error("图片不得大于2MB!");
        return
      }
      const reader = new FileReader()
      // 把Array Buffer转化为blob 如果是base64不需要
      // 转化为base64
      reader.readAsDataURL(file)
      reader.onload = () => {
        this.options.img = reader.result
      }
      this.file = file
      return false;
    },
    okHandel() {
      const vm = this
      vm.confirmLoading = true
      setTimeout(() => {
        vm.confirmLoading = false
        vm.close()
        vm.$message.success('上传头像成功')
      }, 2000)
    },

    realTime(data) {
      if(this.isFirst){
        this.isFirst =false
        return
      }
      this.previews = data
    },
  }
}
</script>
<style lang="less" scoped>
.avatar-upload-preview {
  position: absolute;
  top: 50%;
  transform: translate(50%, -50%);
  width: 200px;
  height: 200px;
  border-radius: 50%;
  box-shadow: 0 0 4px #ccc;
  overflow: hidden;

  img {
    width: 100%;
    height: 100%;
  }
}
</style>

具体就是这样完成的。

写的比较菜,有问题欢迎在评论区提出讨论,谢谢!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值