vue-cropper插件实现图片截取上传组件封装


Posted in Vue.js onMay 27, 2021

基于vue-cropper插件实现图片截取上传组件封装的具体代码,供大家参考,具体内容如下

需求场景:

后台开发需要上传图片并进行相应比例尺寸图片的截取,本组件开发采用Ant Design Vue组件库搭配vue-cropper插件进行封装

实现如下

vue-cropper插件实现图片截取上传组件封装

vue-cropper插件实现图片截取上传组件封装

html

<template>
  <div>
    <a-upload
      name="avatar"
      list-type="picture-card"
      class="avatar-uploader"
      :show-upload-list="false"
      :custom-request="customRequest"
      :before-upload="beforeUpload"
      :style="`width: ${width}; height: ${height};`"
    >
      <img
        v-if="imageUrl && !loading"
        :src="imageUrl"
        alt="avatar"
        :style="`width: ${width}; height: ${height};`"
      />
      <div v-else>
        <a-icon :type="loading ? 'loading' : 'plus'" />
        <div class="ant-upload-text">上传图片</div>
      </div>
    </a-upload>
    <a-modal
      v-model="imageCut.isShowModal"
      title="图片截取"
      width="400px"
      @ok="finish"
      @cancel="imageCut.close"
    >
      <div class="cropper-content" v-if="imageCut.isShowModal">
        <div class="cropper" style="text-align:center">
          <vueCropper
            ref="cropper"
            :img="imageCut.imgFile"
            :outputSize="outputSize"
            :outputType="outputType"
            :info="info"
            :full="full"
            :canMove="canMove"
            :canMoveBox="canMoveBox"
            :original="original"
            :autoCrop="autoCrop"
            :fixed="fixed"
            :fixedNumber="fixedNumber"
            :centerBox="centerBox"
            :infoTrue="infoTrue"
            :fixedBox="fixedBox"
          ></vueCropper>
        </div>
      </div>
    </a-modal>
  </div>
</template>

js

<script>
import { uploadImage } from '@/api/common'
import { VueCropper } from "vue-cropper";
export default {
  name: 'ImageUpload',
  components: { VueCropper },
  data() {
    return {
      loading: false,
      imageCut: {
        isShowModal: false,
        imgFile: '',
        init: imgFile => {
          this.imageCut.imgFile = imgFile
          this.imageCut.isShowModal = true
        },
        close: () => {
          this.imageCut.imgFile = ''
          this.imageCut.isShowModal = false
        }
      }
    }
  },
  props: {
    imageUrl: String,
    width: {
      type: String,
      default: '100px'
    },
    height: {
      type: String,
      default: '100px'
    },
    canCut: {
      type: Boolean,
      default: false
    },
    info: {
      type: Boolean,
      default: false
    }, // 裁剪框的大小信息
    outputSize: {
      type: Number,
      default: 0.8
    }, // 裁剪生成图片的质量
    outputType: {
      type: String,
      default: 'jpeg'
    }, // 裁剪生成图片的格式
    canScale: {
      type: Boolean,
      default: true
    }, // 图片是否允许滚轮缩放
    autoCrop: {
      type: Boolean,
      default: true
    }, // 是否默认生成截图框
    // autoCropWidth: 300, // 默认生成截图框宽度
    // autoCropHeight: 200, // 默认生成截图框高度
    fixedBox: {
      type: Boolean,
      default: false
    }, // 固定截图框大小 不允许改变
    fixed: {
      type: Boolean,
      default: true
    }, // 是否开启截图框宽高固定比例
    fixedNumber: {
      type: Array,
      default: () => [1, 1]
    }, // 截图框的宽高比例
    full: {
      type: Boolean,
      default: true
    }, // 是否输出原图比例的截图
    canMove: {
      type: Boolean,
      default: false
    },
    canMoveBox: {
      type: Boolean,
      default: true
    }, // 截图框能否拖动
    original: {
      type: Boolean,
      default: false
    }, // 上传图片按照原始比例渲染
    centerBox: {
      type: Boolean,
      default: true
    }, // 截图框是否被限制在图片里面
    infoTrue: {
      type: Boolean,
      default: true
    } // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
  },
  methods: {
    beforeUpload(file) {
      const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'
      if (!isJpgOrPng) {
        this.$message.error('请上传JPG或PNG文件!')
      }
      const isLt2M = file.size / 1024 / 1024 < 2
      if (!isLt2M) {
        this.$message.error('请上传2MB以下文件!')
      }
      return isJpgOrPng && isLt2M
    },
    customRequest(file) {
      if (this.canCut) {
        this.readFile(file.file)
      } else {
        this.loading = true
        const formData = new FormData()
        formData.append('fileIdcard', file.file)
        uploadImage(formData).then(res => {
          this.loading = false
          this.$emit('uploadSuccess', res.ossUrl)
        })
      }
    },
    readFile(file) {
      var reader = new FileReader()
      reader.readAsDataURL(file)
      reader.onload = () => {
        this.imageCut.init(reader.result)
      }
    },
    finish() {
      this.$refs.cropper.getCropBlob(data => {
        this.loading = true
        // 上传阿里云服务器
        const formData = new FormData()
        formData.append('fileIdcard', data)
        uploadImage(formData).then(res => {
          this.imageCut.close()
          this.loading = false
          this.$emit('uploadSuccess', res.ossUrl)
        })
      })
    }
  }
}
</script>

css

<style lang="less">
.avatar-uploader > .ant-upload {
  width: 100%;
  height: 100%;
}
.ant-upload-select-picture-card i {
  font-size: 32px;
  color: #999;
}

.ant-upload-select-picture-card .ant-upload-text {
  margin-top: 8px;
  color: #666;
}
.cropper-content {
  .cropper {
    width: auto;
    height: 400px;
  }
}
</style>

组件使用及说明

<image-upload
        :imageUrl="form.diagramUrl"
        @uploadSuccess="uploadSuccess"
        width="160px"
        height="90px"
        :can-edit="canCut"
        :fixed-number="[16,9]"
      />

组件调用时需传入canEdit属性,指定组件是否启动图片选取后的裁剪功能,默认值为不启用裁剪;需裁剪时可传入fixedNumber属性,定义裁剪框的宽高比

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Vue.js 相关文章推荐
Vue 组件注册全解析
Dec 17 Vue.js
vue3.0 自适应不同分辨率电脑的操作
Feb 06 Vue.js
Vue SPA 首屏优化方案
Feb 26 Vue.js
Vue多选列表组件深入详解
Mar 02 Vue.js
vue+django实现下载文件的示例
Mar 24 Vue.js
解读Vue组件注册方式
May 15 Vue.js
vue使用节流函数的踩坑实例指南
May 20 Vue.js
详细聊聊vue中组件的props属性
Nov 02 Vue.js
教你部署vue项目到docker
Apr 05 Vue.js
vue3引入highlight.js进行代码高亮的方法实例
Apr 08 Vue.js
vue二维数组循环嵌套方式 循环数组、循环嵌套数组
Apr 24 Vue.js
vue本地构建热更新卡顿的问题“75 advanced module optimization”完美解决方案
Aug 05 Vue.js
HTML+VUE分页实现炫酷物联网大屏功能
Vue实现动态查询规则生成组件
详解vue身份认证管理和租户管理
vue点击弹窗自动触发点击事件的解决办法(模拟场景)
vue-element-admin项目导入和导出的实现
May 21 #Vue.js
vue2实现provide inject传递响应式
May 21 #Vue.js
vue使用节流函数的踩坑实例指南
You might like
第五节 克隆 [5]
2006/10/09 PHP
PHP中file_exists使用中遇到的问题小结
2016/04/05 PHP
解决php-fpm.service not found问题的办法
2017/06/06 PHP
setTimeout和setInterval的浏览器兼容性分析
2007/02/27 Javascript
Javascript 继承机制的实现
2009/08/12 Javascript
用js写了一个类似php的print_r输出换行功能
2013/02/18 Javascript
js 判断图片是否加载完以及实现图片的预下载
2014/08/14 Javascript
jquery选择器需要注意的问题
2014/11/26 Javascript
javascript中字体浮动效果的简单实例演示
2015/11/18 Javascript
js阻止浏览器默认行为触发的通用方法(推荐)
2016/05/15 Javascript
JS插件amCharts实现绘制柱形图默认显示数值功能示例
2019/11/26 Javascript
Vuex实现购物车小功能
2020/08/17 Javascript
Python代码的打包与发布详解
2014/07/30 Python
初学Python实用技巧两则
2014/08/29 Python
Python解析xml中dom元素的方法
2015/03/12 Python
python处理二进制数据的方法
2015/06/03 Python
Python之父谈Python的未来形式
2016/07/01 Python
Python模块结构与布局操作方法实例分析
2017/07/24 Python
对numpy 数组和矩阵的乘法的进一步理解
2018/04/04 Python
python中append实例用法总结
2019/07/30 Python
基于jupyter代码无法在pycharm中运行的解决方法
2020/04/21 Python
Python selenium环境搭建实现过程解析
2020/09/08 Python
Python利用matplotlib绘制散点图的新手教程
2020/11/05 Python
django中ImageField的使用详解
2020/12/21 Python
CSS的pointer-events属性详细介绍(作用和注意事项)
2014/04/23 HTML / CSS
汽车技术服务与营销专业推荐信
2013/11/29 职场文书
采购部主管岗位职责
2014/01/01 职场文书
承认错误的检讨书
2014/01/30 职场文书
关于随地扔垃圾的检讨书
2014/09/30 职场文书
师德师风自查材料
2014/10/14 职场文书
社区环境卫生倡议书
2015/04/29 职场文书
拾金不昧通报表扬范文
2015/05/05 职场文书
李强优秀员工观后感
2015/06/16 职场文书
2016年社会管理综治宣传月活动总结
2016/03/16 职场文书
SQL中的三种去重方法小结
2021/11/01 SQL Server
css中有哪些方式可以隐藏页面元素及区别
2022/06/16 HTML / CSS