vue中使用图片裁剪cropperjs

1.引入cropperjs

在项目中安装cropperjs,npm地址:https://www.npmjs.com/package/cropperjs

npm install cropperjs

2.封装成组件

组件中使用到了ant-design-vue中的图标,可自行更换

组件主代码

定义了一些属性,并向外暴露出剪裁方法

<template>
  <div class="cropper-wrapper">
    <div class="img-box">
      <img class="cropper-image" :id="imgId" alt="">
    </div>
    <div class="right-con">
      <div v-if="preview" class="preview-box" :id="previewId"></div>
      <div class="button-box">
        <slot>
          <a-upload action="image/upload" :before-upload="beforeUpload" :showUploadList='false'>
            <a-button style=" 150px;" type="primary">选择本机图片</a-button>
          </a-upload>
        </slot>
        <div v-show="insideSrc" class="operates">
           <a-button type="primary"  icon='redo' title='旋转' @click="rotate" />
           <a-button type="primary"  icon='minus' title='缩小' @click="shrink" />
           <a-button type="primary"  icon='plus' title='放大' @click="magnify" />
           <a-button type="primary"  icon='column-width' title='水平翻转' @click="scale('X')" />
           <a-button type="primary"  icon='column-height' title='垂直翻转' @click="scale('Y')" />
           <a-button type="primary"  icon='arrow-up' title='上移' @click="move(0, -moveStep)" />
           <a-button type="primary"  icon='arrow-left' title='左移' @click="move(-moveStep, 0)" />
           <a-button type="primary"  icon='arrow-down' title='下移' @click="move(0, moveStep)" />
           <a-button type="primary"  icon='arrow-right' title='右移' @click="move(moveStep, 0)" />

          <a-button  style=" 150px;margin-top: 10px;" type="primary" @click="crop">{{ cropButtonText }}</a-button >
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Cropper from 'cropperjs'
import './index.less'
import 'cropperjs/dist/cropper.min.css'
export default {
  name: 'Cropper',
  props: {
    src: {
      type: String,
      default: ''
    },
    preview: {
      type: Boolean,
      default: true  //是否显示预览 默认true
    },
    moveStep: {
      type: Number,
      default: 4   //移动一次的大小,默认4
    },
    cropButtonText: {
      type: String,
      default: '裁剪'   //剪裁按钮的文本
    },
    ratio:{
      type: Number,
      default: 5     // 长宽比率,默认5
    }
  },
  data () {
    return {
      cropper: null,
      insideSrc: ''
    }
  },
  computed: {
    imgId () {
      return `cropper${this._uid}`
    },
    previewId () {
      return `cropper_preview${this._uid}`
    }
  },
  watch: {
    src (src) {
      this.replace(src)
    },
    insideSrc (src) {
      this.replace(src)
    }
  },
  methods: {
    beforeUpload (file) {
      const reader = new FileReader()
      reader.readAsDataURL(file)
      reader.onload = (event) => {
        this.insideSrc = event.srcElement.result
      }
      return false
    },
    replace (src) {
      this.cropper.replace(src)
      this.insideSrc = src
    },
    rotate () {
      this.cropper.rotate(90)
    },
    shrink () {
      this.cropper.zoom(-0.1)
    },
    magnify () {
      this.cropper.zoom(0.1)
    },
    scale (d) {
      this.cropper[`scale${d}`](-this.cropper.getData()[`scale${d}`])
    },
    move (...argu) {
      this.cropper.move(...argu)
    },
    crop () {
      this.cropper.getCroppedCanvas().toBlob(blob => {
        this.$emit('on-crop', blob)
      })
    }
  },
  mounted () {
    this.$nextTick(() => {
      let dom = document.getElementById(this.imgId)
      this.cropper = new Cropper(dom, {
        preview: `#${this.previewId}`,
        checkCrossOrigin: true,
        aspectRatio: this.ratio,
      })
    })
  }
}
</script>

组件用到的less

.bg{
  background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC")
}
.cropper-wrapper{
   600px;
  height: 340px;
  .img-box{
    height: 340px;
     430px;
    border: 1px solid #ebebeb;
    display: inline-block;
    .bg;
    img{
      max- 100%;
      display: block;
    }
  }
  .right-con{
    display: inline-block;
     170px;
    vertical-align: top;
    box-sizing: border-box;
    padding: 0 10px;
    .preview-box{
      height: 150px !important;
       100% !important;
      overflow: hidden;
      border: 1px solid #ebebeb;
      .bg;
    }
    .button-box{
      padding: 10px 0 0;
      .operates{
        line-height: 0;
        .ant-btn{
           50px;
          height: 32px;
        }
      }
    }
  }
}

3.组件预览

未选择图片:

选择一张本机图片后:

4.使用组件

首先引入组件,注意位置

import Cropper from '@/components/Cropper'

在页面中使用组件,并定义了一个剪裁方法

<cropper :ratio='2' :cropButtonText="'剪裁并提交'"  @on-crop="handleCroped"></cropper>

剪裁处理方法

handleCroped(blob){
    //将二进制数据放入表单中
    const formData = new FormData()
    formData.append('file', blob)
    //将表单提交到服务器处理 uploadImage 是封装过的上传图片方法
    uploadImage(formData).then((resp) => {
        if(resp.code === 0){
            this.$message.success("上传成功")
            this.$set(this,'image',resp.data)
        }
    })
},

服务器端处理方法:

public Result UploadImage()
  {
    var files = HttpContext.Request.Form.Files;
    var file = files[0];
    string imageName = Guid.NewGuid() + ".png";
    string webSite = configuration["webSite"];
    string path = Path.Combine("upload", DateTime.Now.ToString("yyyy-MM-dd"));
    string dir = Path.Combine(env.ContentRootPath,"wwwroot", path);
    if (!Directory.Exists(dir))
    {
        Directory.CreateDirectory(dir);
    }
    string location = Path.Combine(dir, imageName);
    using (FileStream fs = System.IO.File.Create(location))
    {
        file.CopyTo(fs);
        fs.Flush();
    }
    string url = Path.Combine(webSite , path, imageName);

    return Result.Success(url);
}
原文地址:https://www.cnblogs.com/xiaoqingtian/p/13720951.html