基于vue的图片裁剪vueCropper,不规则/固定比例裁剪,图片裁剪后上传,upload组件,裁剪组件 element UI

实现功能:
在上传图片之前,按照一定比例或不规则进行剪裁,剪裁后上传到服务器,实现绝大部分的图片裁剪上传的需求,代码有注释。
效果图:
在这里插入图片描述

安装

npm install vue-cropper

使用

import { VueCropper } from 'vue-cropper'

上传图片
html

<el-upload
      action=""
      :class="['image-uploader']"
      :show-file-list="false"
      :accept="accept"
      :auto-upload="false"
      :on-change="changeUpload"
    >
      <slot>
        <div v-if="value" class="image-slot">
          <img v-if="/(.+)\.(gif|png|jpg|jpeg)$/.test(value)" :src="value" :style="{maxWidth:size,maxHeight:size}">
          <span @click.stop="$emit('input', '')">点击移除</span>
        </div>
        <el-button v-else type="primary" icon="el-icon-plus">选择图片</el-button>
      </slot>
    </el-upload>
    <el-dialog title="图片剪裁" center width="500px" :visible.sync="clipVisible" append-to-body>
      <div class="cropper-content">
        <div class="cropper" style="text-align:center">
          <vueCropper
            ref="cropper"
            :img="clipOption.img"
            :output-size="clipOption.outputSize"
            :output-type="clipOption.outputType"
            :info="clipOption.info"
            :can-scale="clipOption.canScale"
            :auto-crop="clipOption.autoCrop"
            :auto-crop-width="clipOption.autoCropWidth"
            :auto-crop-height="clipOption.autoCropHeight"
            :fixed="clipOption.fixed"
            :fixed-box="clipOption.fixedBox"
            :fixed-number="clipOption.fixedNumber"
          />
        </div>
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button @click="clipVisible = false">取 消</el-button>
        <el-button type="primary" :loading="loading" @click="finish">确认</el-button>
      </div>
    </el-dialog>
<script>
import { uploadFile } from '@/api/user'
import { VueCropper } from 'vue-cropper'
export default {
  name: 'UploadClipImage',
  components: {
    VueCropper
  },
  props: {
    value: {
      type: [Array, String],
      default() {
        return ''
      }
    },
    required: {
      type: Boolean,
      default: false
    },
    oss: {
      type: [String, Number],
      default: 0
    },
    dirName: { // 上传路径
      type: [String, Number],
      default: 'admin-uploads/'
    },
    accept: {
      type: String,
      default: 'image/gif,image/png,image/jpg,image/jpeg'
    },
    size: { // 图片大小
      type: String,
      default: 'auto'
    },
    pictureSize: { // 上传图片大小
      type: Number,
      default: 0.3
    },
    fixedNumber: { // 裁剪比例
      type: Array,
      default() {
        return [1, 1]
      }
    },
    outputSize: { // 裁剪后图片质量
      type: Number,
      default: 0.8
    },
    outputType: { // 裁剪后图片格式
      type: String,
      default: 'jpg'
    },
    fixed: { // 是否开启截图框宽高固定比例, 若为false,fixedNumber比例无效
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      file_list: [],
      clipVisible: false,
      clipOption: {
        img: '', // 裁剪图片的地址
        info: true, // 裁剪框的大小信息
        outputSize: this.outputSize, // 裁剪生成图片的质量
        outputType: this.outputType, // 裁剪生成图片的格式
        canScale: false, // 图片是否允许滚轮缩放
        autoCrop: true, // 是否默认生成截图框
        autoCropWidth: 280, // 默认生成截图框宽度
        autoCropHeight: 280, // 默认生成截图框高度
        fixedBox: false, // 截图框大小固定 不允许改变
        fixed: this.fixed,
        fixedNumber: this.fixedNumber,
        full: true, // 是否输出原图比例的截图
        canMoveBox: false, // 截图框能否拖动
        original: false, // 上传图片按照原始比例渲染
        centerBox: false, // 截图框是否被限制在图片里面
        infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
        canMove: true
      },
      loading: false,
      fileinfo: {}
    }
  },
  computed: {
    labelString() {
      if (typeof this.$attrs.label === 'string') {
        return this.$attrs.label
      }
      return '上传图片:'
    }
  },
  methods: {
    remove(name) {
      const index = this.file_list.findIndex(v => v.url === name)
      if (index >= 0) {
        this.file_list.splice(index, 1)
        this.$emit('input', this.file_list)
      }
    },
    finish() { // 确定裁剪
      this.loading = true
      this.$refs.cropper.getCropBlob((data) => {
        const params = new FormData()
        params.append('file', data, this.fileinfo.name)
        params.append('dir_name', this.dirName)
        params.append('to_OSS', this.oss)
        uploadFile(params).then(res => {
          if (res.data) {
            this.$emit('input', res.data)
            this.loading = false
            this.clipVisible = false
          }
        })
      })
    },
    changeUpload(file, fileList) {
      const isImage = /image\/[gif|png|jpg|jpeg]/i.test(file.raw.type)
      let imageSize = file.raw.size / 1024 / 1024 < 0.3
      if (this.pictureSize && isImage) {
        imageSize = file.size / 1024 / 1024 < this.pictureSize
      }
      if (isImage) {
        if (isImage && !imageSize) {
          this.$message.error(`上传图片大小不能超过 ${this.pictureSize}M !`)
          return false
        } else {
          this.fileinfo = file
          const url = URL.createObjectURL(file.raw) // 创建一个临时路径
          this.$nextTick(() => {
            this.clipOption.img = url
            this.clipVisible = true
          })
        }
      } else {
        this.$message.error('仅支持上传 png/jpg/jpeg/gif 格式图片')
        return false
      }
    }
  }
}
</script>

结束语:创作不易,动动小手点个赞再走呗~👍,具体不清楚可以联系我哦✌️

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值