vue+elementui+vueCropper裁剪上传图片背景颜色为黑色解决方案

发布于:2025-07-31 ⋅ 阅读:(14) ⋅ 点赞:(0)
组件
<template>
  <div class="avatar-uploader">
    <!-- 头像展示 -->
    <div class="avatar-show">
      <img :src="avatarUrl" v-if="avatarUrl" class="avatar">
      <i class="el-icon-plus avatar-uploader-icon" v-else></i>
    </div>

    <!-- 上传按钮 -->
    <el-upload
        class="avatar-upload"
        action="#"
        :show-file-list="false"
        :before-upload="beforeAvatarUpload"
        :http-request="handleUpload"
    >
      <el-button size="small" type="primary">点击上传</el-button>
      <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过2MB</div>
    </el-upload>

    <!-- 裁剪对话框 -->
    <el-dialog title="裁剪头像" :visible.sync="dialogVisible" width="800px">
      <div class="cropper-content">
        <div class="cropper">
          <vue-cropper
              ref="cropper"
              :img="cropperImg"
              :output-size="1"
              :output-type="'png'"
              :info="true"
              :full="true"
              :can-move="true"
              :can-move-box="true"
              :fixed="true"
              :fixed-number="[1, 1]"
              :center-box="true"
              :auto-crop="true"
              :auto-crop-width="200"
              :auto-crop-height="200"
          ></vue-cropper>
        </div>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="handleCrop">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import { VueCropper } from 'vue-cropper'

export default {
  components: {
    VueCropper
  },
  props: {
    value: String // 用于v-model绑定
  },
  data() {
    return {
      dialogVisible: false,
      cropperImg: '', // 裁剪图片的base64
      // avatarUrl: this.value || require('@/assets/logo.png') // 默认头像
      avatarUrl: null // 默认头像
    }
  },
  methods: {
    // 上传前校验
    beforeAvatarUpload(file) {
      const isJPG = file.type === 'image/jpeg' || file.type === 'image/png'
      const isLt2M = file.size / 1024 / 1024 < 2

      if (!isJPG) {
        this.$message.error('上传头像图片只能是 JPG/PNG 格式!')
      }
      if (!isLt2M) {
        this.$message.error('上传头像图片大小不能超过 2MB!')
      }
      return isJPG && isLt2M
    },

    // 处理上传
    handleUpload(file) {
      const reader = new FileReader()
      reader.onload = (event) => {
        this.cropperImg = event.target.result
        this.dialogVisible = true
        this.$nextTick(() => {
          this.$refs.cropper.replace(event.target.result)
        })
      }
      reader.readAsDataURL(file.file)
    },

    // 处理裁剪
    handleCrop() {
      this.$refs.cropper.getCropBlob((blob) => {
        // 创建FormData对象上传
        const formData = new FormData()
        formData.append('file', blob, 'avatar.png')
        // 这里替换为你的上传API
        this.$axios.post('/api/upload/avatar', formData, {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        }).then(response => {
          this.avatarUrl = response.data.url
          this.$emit('input', this.avatarUrl) // 更新v-model
          this.dialogVisible = false
          this.$message.success('头像上传成功!')
        }).catch(error => {
          this.$message.error('头像上传失败!')
          console.error(error)
        })
      })
    },

    // 也可以使用base64格式
    handleCropBase64() {
      this.$refs.cropper.getCropData((data) => {
        this.avatarUrl = data
        this.$emit('input', data) // 更新v-model
        this.dialogVisible = false
        this.$message.success('头像裁剪成功!')
      })
    }
  },
  watch: {
    value(newVal) {
      this.avatarUrl = newVal
    }
  }
}
</script>

<style scoped>
.avatar-uploader {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.avatar-show {
  width: 150px;
  height: 150px;
  border: 1px dashed #d9d9d9;
  border-radius: 50%;
  overflow: hidden;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-bottom: 20px;
}

.avatar {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
}

.cropper-content {
  display: flex;
  justify-content: center;
}

.cropper {
  width: 500px;
  height: 500px;
}

.el-upload__tip {
  margin-top: 10px;
  text-align: center;
}
</style>

组件调用

<template>
  <div>
    <h2>个人头像设置</h2>
    <avatar-uploader v-model="avatar"></avatar-uploader>
  </div>
</template>

<script>
import AvatarUploader from '@/components/AvatarUploader'

export default {
  components: {
    AvatarUploader
  },
  data() {
    return {
      avatar: '' // 初始头像地址
    }
  }
}
</script>

注意一定要配置:output-type="'png'"


网站公告

今日签到

点亮在社区的每一天
去签到