基于vue-copper的图片裁剪组件封装

项目背景

基于vue3和ts,使用VueCropper完成对图片裁剪组件封装


<template>
  <el-dialog
    :title="title"
    :width="width"
    :append-to-body="true"
    :close-on-click-modal="false"
    v-model:visible="showDialog"
    v-model="showDialog"
    @close="hiddenView"
  >
    <div class="content">
      <div class="cropper-box">
        <vue-cropper
          ref="cropper"
          :can-move="true"
          :auto-crop="true"
          :fixed="true"
          :fixed-number="fixedNumber"
          :img="cropperImg"
          output-type="png"
          @realTime="realTime"
        />
      </div>
      <div class="preview">
        <div class="preview-name">预览</div>
        <img :style="{ width: previewWidth, height: previewHeight, 'border-radius': previewRadius }" :src="previewImg" class="preview-img" />
      </div>
    </div>
    <div class="dialog-footer">
      <el-button size="small" type="primary" @click="submiteImage()">{{ saveButtonTitle }}</el-button>
    </div>
  </el-dialog>
</template>

<script lang="ts" setup>
import 'vue-cropper/dist/index.css'
import { VueCropper } from 'vue-cropper'
import { ref, watch, onMounted } from 'vue'
const props = defineProps({
  width: {
    type: String,
    default: '450px'
  },
  title: {
    type: String,
    default: '编辑头像'
  },
  saveButtonTitle: {
    type: String,
    default: '开始上传'
  },
  show: {
    type: Boolean,
    default: false
  },
  fixedNumber: {
    type: Array,
    default: () => {
      return [1, 1]
    }
  },
  previewWidth: {
    type: String,
    default: '70px'
  },
  previewHeight: {
    type: String,
    default: '70px'
  },
  previewRadius: {
    type: String,
    default: '35px'
  },
  file: [File],
  image: String
})
const emit = defineEmits(['close', 'save'])
const showDialog = ref<Boolean>(false)
const cropperImg = ref<String | undefined>('')
const previewImg = ref<any>('')
const cropper = ref<any>(null)
watch(
  () => props.show,
  (newValue) => {
    showDialog.value = newValue
  },
  {
    deep: true,
    immediate: true
  }
)
watch(
  () => props.image,
  (newValue) => {
    cropperImg.value = newValue
  }
)
onMounted(() => {
  cropperImg.value = props.image
})

function realTime() {
  cropper.value.getCropData((cropperData: any) => {
    previewImg.value = cropperData
  })
}
function submiteImage() {
  // 获取截图的blob数据
  cropper.value.getCropBlob((data: Blob) => {
    emit('save', {
      blob: data,
      file: props.file,
      image: previewImg.value
    })
    hiddenView()
  })
}

function hiddenView() {
  emit('close')
}
</script>

<style lang="scss" scoped>
.cropper-box {
  width: 300px;
  height: 300px;
  margin-right: 15px;
}

.preview {
  position: absolute;
  bottom: 0;
  right: 0;
  .preview-name {
    margin-bottom: 8px;
    font-size: 13px;
    color: #666;
  }
  .preview-img {
    display: block;
  }
}

.content {
  position: relative;
  padding: 0 30px;
}
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  padding-top: 20px;
}
</style>

调用

<input id="uploadAvatarBtn" type="file" accept="image/png, image/jpeg, image/gif, image/jpg" style="display: none" @change="uploadFile" />

<Editimg :show="showEditImage" :file="editFile" :image="editImage" @save="submitImage" @close="showEditImage = false" />
<script>

//修改头像
function setAvatar() {
  document.getElementById('uploadAvatarBtn')?.click()
}

/**
 * 图片操作
 * @param event
 */
function uploadFile(event: Event) {
  const files: any = (event.target as HTMLInputElement).files
  const file = files[0]
  const reader = new FileReader()
  reader.onload = (e: any) => {
    let result
    if (typeof e.target?.result === 'object') {
      // 把Array Buffer转化为blob 如果是base64不需要
      result = window.URL.createObjectURL(new Blob([e.target.result!]))
    } else {
      result = e.target?.result
    }
    editImage.value = result
    editFile.value = file
    showEditImage.value = true
    e.target!.value = ''
  }
  reader.readAsDataURL(file)
}

/**
 * 上传提交头像修改
 * @param data
 */
async function submitImage(data: any) {
  const param = {
    id: 1,
    file: data.blob
  }
  const response = await adminUsersUpdateImgAPI(param)
  AccountInfoFormData.img = response.host + response.file_path
  userStore.setAvatar(AccountInfoFormData.img)
  ElMessage.success('上传成功!')
}
</script>



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值