vue-cropper基本使用, el-upload上传后裁剪,图片裁剪组件封装

类似这种效果 左边是图片 右边是已裁剪图片
vue-cropper基本使用, el-upload上传后裁剪,图片裁剪组件封装_第1张图片

1.安装

npm install vue-cropper

2.main.js

import VueCropper from 'vue-cropper'
Vue.use(VueCropper)

3.裁剪组件弹框 cropperDlg.vue

<template>
  <el-dialog title="图片剪裁" :visible.sync="dialogVisible" class="crop-dialog" append-to-body>
    <div>
      <div class="cropper-content">
        <!-- 剪裁框 -->
        <div class="cropper">
          <VueCropper
            ref="cropper"
            :img="option.img"
            :outputSize="option.size"
            :outputType="option.outputType"
            :info="true"
            :full="option.full"
            :canMove="option.canMove"
            :canMoveBox="option.canMoveBox"
            :original="option.original"
            :autoCrop="option.autoCrop"
            :autoCropWidth="option.autoCropWidth"
            :autoCropHeight="option.autoCropHeight"
            :fixedBox="option.fixedBox"
            @realTime="realTime"
            :fixed="option.fixed"
            listType="picture-card"
            :fixedNumber="fixedNumber"
          ></VueCropper>
        </div>
        <!-- 预览框 -->
        <div
          class="show-preview"
          :style="{
            width: '50%',
            height: '300px',
            overflow: 'hidden',
            margin: '0 25px',
            display: 'flex',
            'align-items': 'center',
          }"
        >
          <div :style="previews.div" class="preview">
            <img :src="previews.url" :style="previews.img" />
          </div>
        </div>
      </div>
      <div class="footer-btn">
        <!-- 缩放旋转按钮 -->
        <div class="scope-btn">
          <el-button type="primary" icon="el-icon-zoom-in" @click="changeScale(1)"></el-button>
          <el-button type="primary" icon="el-icon-zoom-out" @click="changeScale(-1)"></el-button>
          <el-button type="primary" @click="rotateLeft">逆时针旋转</el-button>
          <el-button type="primary" @click="rotateRight">顺时针旋转</el-button>
        </div>
        <!-- 确认上传按钮 -->
        <div class="upload-btn">
          <el-button type="primary" @click="uploadImg('blob')">确定</el-button>
        </div>
      </div>
    </div>
  </el-dialog>
</template>

<script>
export default {

  data() {
    return {
      previews: {}, // 预览数据
      option: {
        img: '', // 裁剪图片的地址  (默认:空)
        size: 1, // 裁剪生成图片的质量  (默认:1)
        full: true, // 是否输出原图比例的截图 选true生成的图片会非常大  (默认:false)
        outputType: 'png', // 裁剪生成图片的格式  (默认:jpg)
        canMove: true, // 上传图片是否可以移动  (默认:true)
        original: false, // 上传图片按照原始比例渲染  (默认:false)
        canMoveBox: true, // 截图框能否拖动  (默认:true)
        autoCrop: true, // 是否默认生成截图框  (默认:false)
        autoCropWidth: 400, // 默认生成截图框宽度  (默认:80%)
        autoCropHeight: 400, // 默认生成截图框高度  (默认:80%)
        fixedBox: false, // 固定截图框大小 不允许改变  (默认:false)
        fixed: true, // 是否开启截图框宽高固定比例  (默认:true)
        fixedNumber: [1.5, 1], // 截图框比例  (默认:[1:1])
      },
      downImg: '#',
    }
  },
  props: ['imgFile', 'fixedNumber', 'dialogVisible'],
  mounted() {
    
    this.$nextTick(() => {
    

      var reader = new FileReader();
      reader.onload = e => {
        let data;
        if (typeof e.target.result === "object") {
          data = window.URL.createObjectURL(new Blob([e.target.result]));
        } else {
          data = e.target.result;
        }
        this.option.img = data;
        
      };
      // 转化为base64
      // reader.readAsDataURL(this.imgFile)
      // 转化为blob
      reader.readAsArrayBuffer(this.imgFile);
    })
  },
  methods: {
    changeScale(num) {
      // 图片缩放
      num = num || 1
      this.$refs.cropper.changeScale(num)
    },
    rotateLeft() {
      // 向左旋转
      this.$refs.cropper.rotateLeft()
    },
    rotateRight() {
      // 向右旋转
      this.$refs.cropper.rotateRight()
    },
    // Update() {
    //   // this.file = this.imgFile
    //   this.option.img = this.imgFile.url
    // },
    realTime(data) {
      // 实时预览
      this.previews = data
    },
    uploadImg(type) {
      // 将剪裁好的图片回传给父组件
      event.preventDefault()
      let that = this
      if (type === 'blob') {
        this.$refs.cropper.getCropBlob((data) => {
          that.$emit('upload', data)
        })
      } else {
        this.$refs.cropper.getCropData((data) => {
          that.$emit('upload', data)
        })
      }
    },
  },
}
</script>
<style>
.cropper-content {
  display: flex;
  display: -webkit-flex;
  justify-content: flex-end;
  -webkit-justify-content: flex-end;
  width: 100%;
}
.cropper-content .cropper {
  width: 50%;
  height: 300px;
}
.cropper-content .show-preview {
  width: 50%;
  height: 300px;
  display: flex;
  display: -webkit-flex;
  justify-content: center;
  -webkit-justify-content: center;
  overflow: hidden;
  border: 1px solid #cccccc;
  /* background: #cccccc; */
  margin-left: 40px;
}
.preview {
  overflow: hidden;
  border: 1px solid #e9ebef;
  background: #e9ebef;
}
.footer-btn {
  margin-top: 30px;
  display: flex;
  display: -webkit-flex;
  justify-content: flex-end;
  -webkit-justify-content: flex-end;
}
.footer-btn .scope-btn {
  width: 50%;
  display: flex;
  display: -webkit-flex;
  
}
.footer-btn .upload-btn {
  width: 50%;
  display: flex;
  display: -webkit-flex;
  justify-content: center;
  -webkit-justify-content: center;
  padding: 0 14px;
}
.footer-btn .btn {
  outline: none;
  display: inline-block;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  -webkit-appearance: none;
  text-align: center;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  outline: 0;
  margin: 0;
  -webkit-transition: 0.1s;
  transition: 0.1s;
  font-weight: 500;
  padding: 8px 15px;
  font-size: 12px;
  border-radius: 3px;
  color: #fff;
  background-color: #67c23a;
  border-color: #67c23a;
}
</style>

vue文件使用 裁剪获取blob

<template>
<div>
 <el-upload
      v-loading="loading"
      :limit="limit"
      ref="upload"
      action="#"
      class="img-uploader"
      list-type="picture-card"
      :file-list="fileList"
      :on-preview="handlePreview"
      :before-upload="beforeUpload"
      :http-request="httpRequest"
      :on-exceed="handleExceed"
      :disabled="disabled"
    > <div class="upload-icon">
        <i class="el-icon-plus"></i>
      </div>  </el-upload>
	    <CropperDlg
	      v-if="showCropper"
	      :dialogVisible.sync="showCropper"
	      :img-file="currentFile"
	      ref="vueCropper"
	      :fixedNumber="fixedNumber"
	      @upload="upload"
	    ></CropperDlg>
    </div>
</template>
<script>
import CropperDlg from '@/components/cropperDlg'
export default {
 
  components: {  CropperDlg },
 data() {
    return {
     fileList:[],
      currentFile: {},
      fixedNumber: [10, 7],
      showCropper: false,//裁剪弹框
      isCropper:true,//上传之前是否显示裁剪
   
    }
  },

  methods: {
    upload(data) { //裁剪成功后获取的图片
      console.log('data: ', data)
  
    },
    // el-upload  上传之前
    beforeUpload(file) {
      if (this.isCropper) {//显示裁剪
        this.currentFile = file
        this.showCropper = true
        return false
      }
      return true
    },
    // 附件改变
    handleChange(file, fileList) {},
    // 文件个数限制
    handleExceed(files, fileList) {
      this.$message.warning(`请最多上传 ${this.limit} 个文件。`)
    },
    // 附件上传
    httpRequest(file) {
      if (!beforeFileUpload(file?.file, this.fileList)) return
      console.log('测试file', file)
    
    },
   
  },
}
</script>
<style lang="less" scoped>

你可能感兴趣的:(vue.js,javascript,前端)