vue+element 图片自动裁剪

本文介绍了如何使用 Vue-cropper 插件实现图片上传前的裁剪功能,包括组件创建、属性配置和事件监听。在父组件中,通过循环遍历图片并设置裁剪框尺寸来实现多张图片裁剪。裁剪完成后,通过子组件的事件传递裁剪后的图片数据。需要注意的是,由于自动裁剪特性,裁剪框宽度和高度为图片宽高减1,且无法直接在父组件中调用裁剪方法。
摘要由CSDN通过智能技术生成

需求:图片上传前,将图片裁剪1px,可上传多张图片

步骤:

1.安装插件

npm install vue-cropper 

2.创建一个图片裁剪组件,在组件中导入,并注册 

<template>
  <div class="Cropper">
    <div class="cropper-container">
      <div class="cropper-el" :style="geth">
        <vue-cropper
          ref="cropper"
          :img="cropperImg"
          :output-size="option.size"
          :output-type="option.outputType"
          :info="true"
          :can-move="option.canMove"
          :can-move-box="option.canMoveBox"
          :fixed-box="option.fixedBox"
          :auto-crop="option.autoCrop"
          :auto-crop-width="optionWidth"
          :auto-crop-height="optionHeigth"
          :center-box="option.centerBox"
          :high="option.high"
          :info-true="option.infoTrue"
          @realTime="realTime"
          :enlarge="option.enlarge"
          :fixed="option.fixed"
          :fixed-number="option.fixedNumber"
          :limitMinSize="option.limitMinSize"
          @imgLoad="imgLoad"
        />
      </div>
    </div>
  </div>
</template>
 
<script>
import { VueCropper } from "vue-cropper";
export default {
  name: "Cropper",
  components: {
    VueCropper,
  },
  props: [
    "cropperImg",//裁剪图片的URL
    "optionWidth",//裁剪框宽
    "optionHeigth",//裁剪框高
    "geth",//样式
    "isDel",//判断是否是裁剪最后一张图
  ],
  data() {
    return {
      previews: {},
      option: {
        img: "", // 裁剪图片的地址
        size: 1, // 裁剪生成图片的质量
        outputType: "png", // 裁剪生成图片的格式 默认jpg
        canMove: false, // 上传图片是否可以移动
        fixedBox: false, // 固定截图框大小 不允许改变
        canMoveBox: false, // 截图框能否拖动
        autoCrop: true, // 是否默认生成截图框
        // 只有自动截图开启 宽度高度才生效
        autoCropWidth: this.optionWidth, // 默认生成截图框宽度
        autoCropHeight: this.optionHeigth, // 默认生成截图框高度
        centerBox: true, // 截图框是否被限制在图片里面
        high: true, // 是否按照设备的dpr 输出等比例图片
        enlarge: 1, // 图片根据截图框输出比例倍数
        mode: "contain", // 图片默认渲染方式 //图片默认渲染方式 contain , cover, 100px, 100% auto
        maxImgSize: 1920, // 限制图片最大宽度和高度
        limitMinSize: [10, 10], // 更新裁剪框最小属性
        // limitMinSize: 10, // 更新裁剪框最小属性
        infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
        fixed: false, // 是否开启截图框宽高固定比例 (默认:true)
        // fixedNumber: [1, 1] // 截图框的宽高比例 ==>> 这个参数目前没有作用(作者解释的)
        fixedNumber: [1, 1], // 截图框的宽高比例
      },
    };
  },
  methods: {
    // 裁剪时触发的方法,用于实时预览
    realTime(data) {
      this.previews = data;
      // this.$refs.cropper.getCropBlob((data) => {
      //   console.log("51511515");
      // });
      this.$refs.cropper.clearCrop();
      // console.log(this.previews.url);
      //  console.log(3333)
    },
    // 图片加载的回调 imgLoad 返回结果success, error
    imgLoad(e) {
      if (e === "success") {       
        this.$nextTick(() => {
          // 获取裁剪之后的图片,默认blob,也可以获取base64的图片
          this.$refs.cropper.getCropBlob((data) => {
            let config = { data: data, isDel: this.isDel };
            this.$emit("uploadImg", config);
          });
        });
      }
    },  
  },
};
</script>
 
<style lang="scss" scoped>
.Cropper {
  .cropper-el {
    flex-shrink: 0;
  }
  .cropper-container {
    display: block;
    justify-content: space-between;
    .prive-el {
      flex: 1;
      align-self: center;
      text-align: center;
      .prive-style {
        margin: 0 auto;
        flex: 1;
        -webkit-flex: 1;
        display: flex;
        display: -webkit-flex;
        justify-content: center;
        -webkit-justify-content: center;
        overflow: hidden;
        background: #ededed;
        margin-left: 40px;
      }
      .preview {
        overflow: hidden;
      }
      .el-button {
        margin-top: 20px;
      }
    }
  }
}
</style>
<style lang="scss">
.cropper-box-canvas img {
  width: 100% !important;
  height: 100% !important;
}
</style>

父组件:

<template>
  <div>
    <el-form ref="form" :model="form" label-width="7rem" :rules="rules">
      <el-form-item label="帖子图片">
        <el-upload
          class="upload-demo uploadDemoMy"
          :action="baseUrl"
          multiple
          :limit="10"
          :file-list="fileListImg"
          :auto-upload="false"
          accept="image/*"
          :show-file-list="true"
          :on-remove="handleRemove"
          :on-change="handleChangeIMG"
          list-type="picture"
        >
          <el-button size="small" type="primary"
            >点击上传</el-button
          >
        </el-upload>
        <div class="ordinaryshowImg">
          <div
            v-for="(item, index) in cropperImglist"
            :key="index"
            style="opacity: 0; position: absolute"
          >
            <vueCropper
              :cropperImg="cropperImglist[index]"
              :optionWidth="optionWidth"
              :optionHeigth="optionHeigth"
              :imgH="imgH"
              :imgW="imgW"
              :geth="geth"
              ref="sonCropper"
              :isDel="isDel"
              @uploadImg="uploadImg"
              style="opacity: 0; position: absolute"
            />
          </div>
        </div>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
import vueCropper from "./vueCropper.vue";
export default {
  components: {
    vueCropper,
  },
  data() {
    return {
      form: {
        postsPicList: [], //图片地址
      },
      rules: {},
      fileListImg: [], //图片List
      baseUrl: "",
      optionWidth: 0,
      optionHeigth: 0,
      cropperImglist: [], //url
      myimgsrcList: [], //截取后图的url
      myimgListdata: [], //截取后图的数据
      isDel: 0,
    };
  },
  methods: {
    onSubmit() {
      this.form.postsPicList = [];
      this.$refs.form.validate((valid) => {
        if (valid) {
          if (this.fileListImg.length != 0) {
            this.upLoadfileToServerI();
          } else {
            this.$message.error("请选择上传的图片或视频");
          }
        }
      });
    },
    // 裁剪图片
    upLoadfileToServerI() {
      // 将选中的图片遍历,每张图片都对应一个裁剪框,对裁剪组件隐藏
      //  this.cropperImglist用来保存选中图片的URL,以此数组循环,得到裁剪组件
      this.isDel = 0;
      this.fileListImg.forEach((item, index) => {
        let file = item.raw;
        let url = URL.createObjectURL(file);
        this.cropperImglist.push(url);
        this.myimgsrcList.push(url);
        let that = this;
        let img = new Image();
        img.src = url;
        img.onload = function () {
          //改变裁剪框的大小
          that.optionWidth = img.width - 1;
          that.optionHeigth = img.height - 1;
          that.geth = `height:${img.height}px;width:${img.width}px;`;
        };
      });
    },
    //移除图片
    handleRemove(file, fileList) {
      this.fileListImg = fileList;
    },
    // 选择的图片
    handleChangeIMG(file, fileList) {
      this.fileListImg = fileList;
    },
    // 获取截取后的图片,并获取上传链接 裁剪完成后,子组件会触发这个方法,可获取裁剪后的图片
    uploadImg(config) {
      this.isDel++; //每裁剪一张图 就+1
      this.myimgListdata.push(config.data);
      //   裁剪到最后一张图片时
      if (config.isDel + 1 === this.fileListImg.length) {
        console.log(this.myimgListdata); //所有截取后的图片
      }
    },
  },
};
</script>

<style lang="scss" scoped>
</style>

注意:

1.这实际是一个裁剪框组件,需要给一个宽高。

2.由于是自动裁剪,只裁剪1px 裁剪框宽高等于图片宽高-1。

3.经各种尝试,也无法在父组件中直接调用this.$refs.cropper.getCropBlob( )方法,不会执行。

4.不能将裁剪后的图片直接展示出来,会重发触发imgLoad方法,导致图片数量增加。具体需要研究深层的原理。

 

个人经验,如有更简便的方法欢迎分享

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值