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表单验证之禁止input输入框输入空格
Dec 03 Vue.js
vue实现购物车的小练习
Dec 21 Vue.js
Vue实现简易购物车页面
Dec 30 Vue.js
vue3中轻松实现switch功能组件的全过程
Jan 07 Vue.js
Vuex实现简单购物车
Jan 10 Vue.js
如何使用RoughViz可视化Vue.js中的草绘图表
Jan 30 Vue.js
如何在 Vue 中使用 JSX
Feb 14 Vue.js
vue backtop组件的实现完整代码
Apr 07 Vue.js
vue项目两种方式实现竖向表格的思路分析
Apr 28 Vue.js
Vue监视数据的原理详解
Feb 24 Vue.js
vue使用localStorage持久性存储实现评论列表
Apr 14 Vue.js
vue项目如何打包之项目打包优化(让打包的js文件变小)
Apr 30 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
php实现中文转数字
2016/02/18 PHP
PHP在linux上执行外部命令的方法
2017/02/06 PHP
javascript中关于break,continue的特殊用法与介绍
2012/05/24 Javascript
分享JavaScript获取网页关闭与取消关闭的事件
2013/12/13 Javascript
深入理解Javascript里的依赖注入
2014/03/19 Javascript
用js读、写、删除Cookie代码续篇
2014/12/03 Javascript
移动设备web开发首选框架:zeptojs介绍
2015/01/29 Javascript
easyui Droppable组件实现放置特效
2015/08/19 Javascript
jqPlot jQuery绘图插件的使用
2016/06/18 Javascript
js 弹出虚拟键盘修改密码的简单实例
2016/10/10 Javascript
利用Node.js对文件进行重命名
2017/03/12 Javascript
javascript基本常用排序算法解析
2017/09/27 Javascript
AngularJS 教程及实例代码
2017/10/23 Javascript
react-native android状态栏的实现
2018/06/15 Javascript
浅谈Vue.js组件(二)
2019/04/09 Javascript
JavaScript中AOP的实现与应用
2019/05/06 Javascript
Node.js从字符串生成文件流的实现方法
2019/08/18 Javascript
js实现3D照片墙效果
2019/10/28 Javascript
微信小程序自定义头部导航栏(组件化)
2019/11/15 Javascript
详解微信小程序(Taro)手动埋点和自动埋点的实现
2021/03/02 Javascript
[04:40]2016个国际邀请赛中国区预选赛场地——华西村观战指南
2016/06/25 DOTA
[04:10]2018年度CS GO玩家最喜爱的主播-完美盛典
2018/12/16 DOTA
浅谈python中copy和deepcopy中的区别
2017/10/23 Python
Python判断一个三位数是否为水仙花数的示例
2018/11/13 Python
python矩阵的转置和逆转实例
2018/12/12 Python
Python实现决策树并且使用Graphviz可视化的例子
2019/08/09 Python
你还在@微信官方?聊聊Python生成你想要的微信头像
2019/09/25 Python
Xadmin+rules实现多选行权限方式(级联效果)
2020/04/07 Python
详解Django中views数据查询使用locals()函数进行优化
2020/08/24 Python
Zooplus葡萄牙:欧洲领先的网上宠物商店
2018/07/01 全球购物
企业内部培训方案
2014/02/04 职场文书
抄作业检讨书
2014/02/17 职场文书
工业自动化专业自荐信范文
2014/04/10 职场文书
文明班级建设方案
2014/05/15 职场文书
医院合作意向书范本
2015/05/08 职场文书
教师素质教育心得体会
2016/01/19 职场文书