vue3实现图片裁剪上传功能

1、安装引入vue-cropper(可参考:https://www.npmjs.com/package/vue-cropper

        npm install vue-cropper@next
        import 'vue-cropper/dist/index.css'
        import { VueCropper }  from "vue-cropper";
2、组件完整代码
<template>
  <div class="avatar-container" @click="editImage()">
    <img :src="options.img" title="点击上传" class="img-box" />
    <el-dialog title="裁剪图片" v-model="dialogVisible" width="800px" append-to-body @opened="openDialog" @close="closeDialog">
      <el-row>
        <el-col :span="12" style="height: 300px;">
          <vue-cropper
            ref="cropper"
            :img="options.img"
            :info="true"
            :autoCrop="options.autoCrop"
            :autoCropWidth="options.autoCropWidth"
            :autoCropHeight="options.autoCropHeight"
            :fixedBox="options.fixedBox"
            :outputType="options.outputType"
            @realTime="realTime"
            v-if="showCropper"
          />
        </el-col>
        <el-col :span="12" style="height: 300px;">
          <div class="preview-box">
            <img :src="previews.url" :style="previews.img" />
          </div>
        </el-col>
      </el-row>
      <el-row style="margin-top: 12px;">
        <el-col :span="12">
          <el-row>
            <el-col :span="8">
              <el-upload
                action="#"
                :http-request="() => {}"
                :before-upload="beforeUpload"
                :show-file-list="false"
              >
                <el-button>选择</el-button>
              </el-upload>
            </el-col>
            <el-col :span="4">
              <el-button :icon="Plus" @click="changeScale(1)"></el-button>
            </el-col>
            <el-col :span="4">
              <el-button :icon="Minus" @click="changeScale(-1)"></el-button>
            </el-col>
            <el-col :span="4">
              <el-button :icon="RefreshLeft" @click="rotateLeft()"></el-button>
            </el-col>
            <el-col :span="4">
              <el-button :icon="RefreshRight" @click="rotateRight()"></el-button>
            </el-col>
          </el-row>
        </el-col>
        <el-col :span="4" :offset="8">
          <el-button type="primary" @click="uploadImg()">提 交</el-button>
        </el-col>
      </el-row>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { Plus, Minus, RefreshLeft, RefreshRight } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { uploadImage } from "@/api/target/manage";
import "vue-cropper/dist/index.css";
import { VueCropper } from "vue-cropper";

const { proxy } = getCurrentInstance();
const props = defineProps({
	dataInfo: {
		type: Object,
		default: {}
	}
})
const dialogVisible = ref(false);
const showCropper = ref(false);
// cropper配置  更多配置可参考 https://www.npmjs.com/package/vue-cropper
const options = reactive({
  img: props.dataInfo.img, // 裁剪图片的地址
  autoCropWidth: 200, // 默认生成截图框宽度 默认容器的 80%
  autoCropHeight: 200, // 默认生成截图框高度 默认容器的 80%
  outputType: "png", // 裁剪生成图片的格式 jpeg, png, webp
  autoCrop: true, // 是否默认生成截图框
  fixedBox: false, // 固定截图框大小
});
const previews = ref({
  url: ''
})

watch(
	() => props.dataInfo,
	() => {
    options.img = props.dataInfo.img;
	},
	{ deep: true, immediate: true }
)

// 编辑图片
const editImage = () => {
  dialogVisible.value = true;
}

// 打开裁剪弹窗
const openDialog = () => {
  showCropper.value = true;
}
// 修改图片大小 正数为变大 负数变小
const changeScale = (num: number) => {
  num = num || 1;
  proxy.$refs.cropper.changeScale(num);
}
// 向左边旋转90度
const rotateLeft = () => {
  proxy.$refs.cropper.changeScale();
}
// 向右边旋转90度
const rotateRight = () => {
  proxy.$refs.cropper.rotateRight();
}
// 上传图片处理
const beforeUpload = (rawFile: any) => {
  if (rawFile.type.indexOf("image/") == -1) {
    ElMessage.error('请上传图片类型文件!')
    return false
  }
  if (rawFile.size / 1024 / 1024 > 2) {
    ElMessage.error('文件大小不能超过2MB!')
    return false
  }
  const reader = new FileReader();
  reader.readAsDataURL(rawFile);
  reader.onload = () => {
    options.img = reader.result;
  };
}
// 上传图片
const uploadImg = () => {
  proxy.$refs.cropper.getCropBlob((data: any) => {
    let formData = new FormData();
    formData.append("file", data);
    let params = {
      id: 1
    }
    uploadImage(params, formData).then((res: any) => {
      if(res.code == 200) {
        options.img = res.data;
        props.dataInfo.img = options.img;
        showCropper.value = false;
        dialogVisible.value = false;
        ElMessage.success("上传成功!");
      } else {
        ElMessage.error(res.message || '上传失败!')
      }
    });
  });
}
// 实时预览事件
const realTime = (data: any) => {
  previews.value = data;
}
// 关闭弹窗
const closeDialog = () => {
  options.img = props.dataInfo.img;
}
</script>

<style lang='scss' scoped>
.avatar-container {
  position: relative;
  display: flex;
  justify-content: center;
  height: 10vw;
  width: 10vw;
  &:hover {
    &::after {
      content: "+";
      position: absolute;
      width: 100%;
      height: 100%;
      border-radius: 50%;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: 30px;
      font-weight: bold;
      color: #fff;
      background: rgba(0, 0, 0, 0.5);
      cursor: pointer;
    }
  }
  .img-box {
    border-radius: 50%;
    border: 1px solid #ccc;
    width: 10vw;
    height: 10vw;
  }
}
.preview-box {
  position: absolute;
  top: 50%;
  transform: translate(50%, -50%);
  width: 200px;
  height: 200px;
  border-radius: 50%;
  border: 1px solid #ccc;
  overflow: hidden;
}
</style>

3、组件使用

<template> 
  <div class="avatar-box">
    <Avatar :dataInfo="dataInfo" />
  </div>
</template>  
  
<script setup lang="ts">  
import { ref } from 'vue';
import Avatar from '@/components/Avatar/index.vue'  
interface DataFace {
	img: string
	[propName: string]: any
}
const dataInfo = ref<DataFace>({ 
  img: 'https://img1.baidu.com/it/u=3717210657,1724010864&fm=253&fmt=auto&app=138&f=PNG?w=500&h=500'
})

</script>
<style lang="scss" scoped>
.avatar-box {
  width: 300px;
  display: flex;
  justify-content: center;
}
</style>

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3提供了许多实用的第三方库来处理图片上传裁剪,下面我将介绍并展示如何在Vue 3中实现这些功能。 首先,我们需要使用一个图片上传的库,比较常用的是`vue-upload-component`。该库提供了一种简单的方式来处理文件上传,并且可以在上传文件显示进度条。可以通过`npm`或`yarn`来安装该库。 安装完成后,在需要上传图片的组件中导入并注册`vue-upload-component`,并在模版中使用`<file-upload></file-upload>`标签来创建上传按钮。你还可以设置其他选项,比如允许上传图片类型、最大文件大小等等。 接下来,我们需要使用一个图片裁剪的库,比较常用的是`vue-cropperjs`。该库通过集成Cropper.js来提供图片裁剪功能。同样地,可以通过`npm`或`yarn`来安装该库。 安装完成后,在需要裁剪图片的组件中导入并注册`vue-cropperjs`,并在模版中使用`<vue-cropper></vue-cropper>`标签来创建裁剪区域。你可以设置一些属性来定义裁剪区域的大小、裁剪框的宽高比例等等。 接下来,你可以监听图片上传事件,获取到上传图片文件。然后将该文件传递给`vue-cropperjs`组件,用于裁剪。在裁剪完成后,你可以获取到裁剪后的图片数据,可以根据需要进行保存或展示。 综上所述,使用Vue 3实现图片上传裁剪非常简单。可以借助第三方库快速完成这些功能。希望以上回答对你有所帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值