vue-cropper实现图片裁剪上传

1.图片裁剪组件photoCut.vue

<template>
  <div>
    <div class="info-item">
      <div class="line">
        <div class="cropper-content">
          <div class="cropper" style="text-align: center">
            <div v-show="!option.img" class="uploadimg">
              <div style="  padding-top: 20px;">
                <i class="ic-upload-cloud iconfont"/>
              </div>
              <div style="line-height:22px;color:#79818B;margin-top: -33px">
                支持jpg、png格式的图片,大小不超过2M
              </div>
              <div style="margin-top: 30px">
                <Button class="but" @click="newUpload">上传图片</Button>
                <input type="file" id="uploads" :value="imgFile" style="position:absolute; clip:rect(0 0 0 0);"
                       accept="image/png, image/jpeg,image/jpg" @change="uploadImg($event, 1)">
              </div>
            </div>
            <vueCropper
              v-show="option.img"
              ref="cropper"
              :img="option.img"
              :outputSize="option.size"
              :outputType="option.outputType"
              :info="option.info"
              :full="option.full"
              :canMove="option.canMove"
              :canMoveBox="option.canMoveBox"
              :canScale="option.canScale"
              :original="option.original"
              :autoCrop="option.autoCrop"
              :autoCropWidth="option.autoCropWidth"
              :autoCropHeight="option.autoCropHeight"
              :fixedBox="option.fixedBox"
              :centerBox="option.centerBox"
              :enlarge="option.enlarge"
              :mode="option.mode"
              @realTime="realTime"
              @imgLoad="imgLoad"
            ></vueCropper>
          </div>
          <div class="yulanimg" style="position: relative">
            <div v-show="option.img">
              <div class="show-preview" :style="previewStyle1" style="top: -63px;left: -60px;">
                <div :style="previews.div" class="preview">
                  <img v-show="option.img" :src="previews.url" :style="previews.img">
                </div>
              </div>
              <div class="show-preview" :style="previewStyle2" style="top: 29px;left: -60px;">
                <div :style="previews.div" class="preview">
                  <img v-show="option.img" :src="previews.url" :style="previews.img">
                </div>
              </div>
              <div class="show-preview" :style="previewStyle3" style="top: 100px;left: -60px;">
                <div :style="previews.div" class="preview">
                  <img v-show="option.img" :src="previews.url" :style="previews.img">
                </div>
              </div>
            </div>
            <div v-show="!option.img">
              <div class="imgdiv1">
              </div>
              <div class="imgdiv2">
              </div>
              <div class="imgdiv3">
              </div>
            </div>
            <div class="show-preview"
                 style="height: 40px;width: 100%;
                        top: 296px;
                        left: 0px;">
              <Button class="but" v-show="option.img" @click="newUpload">重新上传</Button>
              <div v-show="!option.img" style="font-size:12px;
                    line-height:22px;
                    color:rgba(139,148,165,1);">预览
              </div>
            </div>
          </div>
        </div>
      </div>
      <!--<input type="button" class="btn btn-blue" value="上传头像" @click="finish('blob')">-->
    </div>
    <div flex="main:center" style="margin: 30px 0px  0px;">
      <Button @click="cancel" class=" resetBtn" size="large" style="width: 76px">取消</Button>
      <Button @click="finish('blob')"  :loading="buttonLoading" type="primary" size="large"  style="width: 76px">保存</Button>
    </div>
  </div>
</template>

<script>
  import {VueCropper} from 'vue-cropper'
  import {Button, Icon} from "view-design"
  import {uploadImg}  from './api/index'

  export default {
    data() {
      return {
        buttonLoading:false,
        previewStyle1: {},
        previewStyle2: {},
        previewStyle3: {},
        headImg: '',
        //剪切图片上传
        crap: false,
        previews: {},
        option: {
          img: '',//裁剪图片的地址
          outputSize: 1, //剪切后的图片质量(0.1-1)
          outputType: 'png',//裁剪生成图片的格式
          info: true,//裁剪框的大小信息
          canScale: true,//图片是否允许滚轮缩放
          autoCrop: true,//是否默认生成截图框
          autoCropWidth: 250,//默认生成截图框宽度
          autoCropHeight: 250,//默认生成截图框高度
          //fixed	是否开启截图框宽高固定比例true
          //fixedNumber	截图框的宽高比例
          full: false,//输出原图比例截图 false
          fixedBox: true,//固定截图框大小 不允许改变
          canMove: true,//上传图片是否可以移动
          canMoveBox: false,//截图框能否拖动
          original: false,//上传图片按照原始比例渲染
          centerBox: false,// centerBox	截图框是否被限制在图片里面
          // high	是否按照设备的dpr 输出等比例图片
          infoTrue: true, // 为展示真实输出图片宽高 false 展示看到的截图框宽高
          // maxImgSize	限制图片最大宽度和高度
          enlarge: 0.5, //图片根据截图框输出比例倍数
          mode: 'contain'	//图片默认渲染方式
        },
        fileName: '',  //本机文件地址
        //downImg: '#',
        imgFile: '',
        //uploadImgRelaPath: '', //上传后的图片的地址(不带服务器域名)
      }
    },
    components: {
      VueCropper, Button, Icon
    },
    methods: {
      newUpload() {
        document.getElementById("uploads").click()
      },
      //上传图片(点击上传按钮)
      finish(type) {
        this.buttonLoading=true
        if (!this.fileName) {
          this.buttonLoading=false
          this.$Message.info("请上传logo!")
          return
        }
        if (type === 'blob') {
          // 获取截图的blob数据
          this.$refs.cropper.getCropBlob((data) => {
            // let img = window.URL.createObjectURL(data)
            // this.model = true;
            // this.modelSrc = img;
            //裁剪后的图片显示
            // this.option.img = this.modelSrc;
            var forms = new FormData()
            forms.append('file', data)
            uploadImg(forms).then(res=>{
              this.buttonLoading=false
                if (res.status == 200) {
                  // this.$Message.success(res.message)
                  this.$emit("uploaderSuccess", res.data.filePath)
                  this.cancel()
                } else {
                  this.$Message.error(res.message)
                }
            }).catch(res=>{
              this.buttonLoading=false
              this.$Message.error(res.message)
            })
            // axios.post(
            //   "/bnd-admin/v1/file/uploadImage",
            //   forms,
            //   {
            //     headers: {
            //       'Authorization': 'eyJ2ZXIiOiIxLjAiLCJ0eXAiOiIxIiwiZXB0IjoyLCJraWQiOiJlMDhhYzY2Mi02YWU2LTRiZjktYjlmNS1kYzdmZTMxZTdlMjQiLCJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJVQUFDIiwiaWF0IjoxNTc5MDcyNTk3LCJuYmYiOjE1NzkwNzI1OTcsImF1ZCI6IldFQiIsInN1YiI6Ik5Eb2xSVFlsUWpFbFFVRWxSVFlsUWpRbE9FSXgifQ.AJrhGLNeHj1Csl-3FmkdnaahbLP2QveXkFVfr6GmV3IdFfLBXBK2_G8qn5_ljU_XqWAf5s0Pul1IcgOvzT4WKtuuAOS6bL_GVOEyiVu_oXmqhXxJfUt00FkIeUfEP3IwBEVK9cbYmhrc0a68bnLCEjGUbpj6gocPheZKzAM0XlxXZCob',
            //       'Content-Type': 'multipart/form-data'
            //     }
            //   }
            // ).then(res => {
            //   if (res.data.status == 200) {
            //     console.log(res)
            //     // this.$Message.success("上传成功")
            //     // this.$emit("uploaderSuccess", res.data.data.filePath)
            //     // this.cancel()
            //   } else {
            //     this.$Message.error("上传失败1")
            //   }
            //
            // }).catch(res => {
            //   this.$Message.error("上传失败2")
            // });
          })
        } else {
          // 获取截图的base64 数据
          this.$refs.cropper.getCropData((data) => {
            this.model = true;
            this.modelSrc = data;
          })
        }
      },
      // 实时预览函数
      realTime(data) {
        var previews = data;
        this.previewStyle1 = {
          width: previews.w + "px",
          height: previews.h + "px",
          overflow: "hidden",
          margin: "0",
          transform: `scale(${80 / previews.w})`
        };
        this.previewStyle2 = {
          width: previews.w + "px",
          height: previews.h + "px",
          overflow: "hidden",
          margin: "0",
          transform: `scale(${60 / previews.w})`
        };
        //固定为40宽度
        this.previewStyle3 = {
          width: previews.w + "px",
          height: previews.h + "px",
          overflow: "hidden",
          margin: "0",
          transform: `scale(${40 / previews.w})`
          // zoom: 40 / previews.w
        };
        this.previews = data
      },
      cancel() {
        this.$emit("cnacelModal")
      },
      //选择本地图片
      uploadImg(e, num) {
        console.log('uploadImg',e.target.value);
        var _this = this;
        //上传图片
        var file = e.target.files[0]
        _this.fileName = file.name;
       if (!/\.(jpeg|jpg|png)$/.test(e.target.value)) {
          e.target.value=''
          this.$Message.info("只支持jpg、png、jpeg格式图片!")
          return
        }
        if (file.size / 1024 / 1024 > 2) {
          e.target.value=''
          this.$Message.info("图片不得大于2M!")
          return
        }
        var reader = new FileReader();
        reader.onload = (e) => {
          let data;
          if (typeof e.target.result === 'object') {
            // 把Array Buffer转化为blob 如果是base64不需要
            data = window.URL.createObjectURL(new Blob([e.target.result]))
          } else {
            data = e.target.result
          }
          if (num === 1) {
            _this.option.img = data
          } else if (num === 2) {
            _this.example2.img = data
          }
        }
        // 转化为base64
        // reader.readAsDataURL(file)
        // 转化为blob
        reader.readAsArrayBuffer(file);

      },
      imgLoad(msg) {
        console.log('imgLoad')
        console.log(msg)
      }
    },

  }
</script>

<style scoped lang="less">
  /deep/ .ivu-btn > .ivu-icon {
    width: 14px;
    height: 14px;
    line-height: 1;
  }
  .resetBtn{
    margin-right: 16px;
    background:rgba(240,242,245,1);
    border: 1px solid rgba(240,242,245,1);
    color: #363A40;
  }
  .resetBtn:hover{
    background: #E5E6E8;
  }
  .ic-upload-cloud{
    color:#CDD6E1;
    font-size: 112px;
  }
  /deep/ .cropper-view-box {
    outline: 1px dashed white;
  }

  /deep/ span.cropper-view-box {
    margin-bottom: 16px;
  }

  /deep/ div.cropper-crop-box:after {
    content: '鼠标滚轮缩放图片大小,鼠标拖拽调整图片位置';
    color: white;
    font-size: 12px;
    white-space: nowrap;
    margin-top: 16px;
  }

  /deep/ .crop-info {
    display: none;
  }

  /deep/ .vue-cropper {
    background-image: none;
  }

  .but {
    color: #4183FA;
    border-color: white
  }

  .but:hover {
    background: #3473E7;
    color: white;
  }

  .uploadimg {
    width: 350px;
    height: 350px;
    background: rgba(248, 250, 255, 1);
    opacity: 1;
  }

  .yulanimg {
    margin-left: 2px;
    width: 128px;
    height: 350px;
    background: rgba(248, 250, 255, 1);
    opacity: 1;
  }

  .imgdiv1 {
    width: 80px;
    height: 80px;
    background: #DDDFE8;
    border-radius: 50%;
    border: 2px solid white;
    margin: 21px 0px 0px 25px;
  }

  .imgdiv2 {
    width: 60px;
    height: 60px;
    background: #DDDFE8;
    border-radius: 50%;
    border: 2px solid white;
    margin: 23px 0px 0px 34px;
  }

  .imgdiv3 {
    width: 40px;
    height: 40px;
    background: #DDDFE8;
    border-radius: 50%;
    border: 2px solid white;
    margin: 20px 0px 0px 45px;
  }

  .info {
    width: 720px;
    margin: 0 auto;

    .oper-dv {
      height: 20px;
      text-align: right;
      margin-right: 100px;

      a {
        font-weight: 500;

        &:last-child {
          margin-left: 30px;
        }
      }
    }

    .info-item {
      margin-top: 15px;

      label {
        display: inline-block;
        width: 100px;
        text-align: right;
      }

      .sel-img-dv {
        position: relative;

        .sel-file {
          position: absolute;
          width: 90px;
          height: 30px;
          opacity: 0;
          cursor: pointer;
          z-index: 2;
        }

        .sel-btn {
          position: absolute;
          cursor: pointer;
          z-index: 1;
        }
      }
    }
  }

  .cropper-content {
    display: flex;
    display: -webkit-flex;
    justify-content: flex-end;
    -webkit-justify-content: flex-end;

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

    .show-preview {
      width: 250px;
      height: 250px;
      position: absolute;
      flex: 1;
      -webkit-flex: 1;
      display: flex;
      display: -webkit-flex;
      justify-content: center;
      -webkit-justify-content: center;

      .preview {
        overflow: hidden;
        border-radius: 50%;
        border: 6px solid white;
        background: #DDDFE8;
        margin-left: 40px;
      }
    }
  }

  .cropper-content .show-preview .preview {
    margin-left: 0;
  }

</style>

2.图片上传接口index.js文件

import axios from "axios"

const $postImg = (url, data) => {
  return axios({
    method: 'post',
    url,
    data,
    headers: { 'Content-Type': 'multipart/form-data' }
  })
}

export const uploadImg = (obj) => {
  return $postImg('图片上传路径', obj)
}

你可能感兴趣的:(vue-cropper实现图片裁剪上传)