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从后台渲染文章列表以及根据id跳转文章详情详解
Dec 14 Vue.js
Vue——解决报错 Computed property &quot;****&quot; was assigned to but it has no setter.
Dec 19 Vue.js
基于vue+echarts数据可视化大屏展示的实现
Dec 25 Vue.js
vue 使用class创建和清除水印的示例代码
Dec 25 Vue.js
vue组件是如何解析及渲染的?
Jan 13 Vue.js
如何在vue 中使用柱状图 并自修改配置
Jan 21 Vue.js
vue 实现上传组件
May 31 Vue.js
Vue3.0中Ref与Reactive的区别示例详析
Jul 07 Vue.js
vue中div禁止点击事件的实现
Apr 02 Vue.js
vue中的可拖拽宽度div的实现示例
Apr 08 Vue.js
分享一个vue实现的记事本功能案例
Apr 11 Vue.js
Vue2项目中对百度地图的封装使用详解
Jun 16 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
Zend公司全球首推PHP认证
2006/10/09 PHP
2.PHP入门
2006/10/09 PHP
PHP脚本数据库功能详解(中)
2006/10/09 PHP
浅析虚拟主机服务器php fsockopen函数被禁用的解决办法
2013/08/07 PHP
php防止站外远程提交表单的方法
2014/10/20 PHP
JQuery魔力之$(&quot;tagName&quot;)与selector
2012/03/05 Javascript
js弹出框轻量级插件jquery.boxy使用介绍
2013/01/15 Javascript
js 弹出框只弹一次(二次修改之后的)
2013/11/26 Javascript
JavaScript中对循环语句的优化技巧深入探讨
2014/06/06 Javascript
javascript获取文档坐标和视口坐标
2015/05/26 Javascript
JavaScript拖拽、碰撞、重力及弹性运动实例分析
2016/01/08 Javascript
JavaScript动态生成二维码图片
2016/04/20 Javascript
BootStrap+Angularjs+NgDialog实现模式对话框
2016/08/24 Javascript
分享一个原生的JavaScript拖动方法
2016/09/25 Javascript
jQuery插件JWPlayer视频播放器用法实例分析
2017/01/11 Javascript
JavaScript基本类型值-Undefined、Null、Boolean
2017/02/23 Javascript
element-ui 上传图片后清空图片显示的实例
2018/09/04 Javascript
babel7.x和webpack4.x配置vue项目的方法步骤
2019/05/12 Javascript
vue点击当前路由高亮小案例
2019/09/26 Javascript
js中位数不足自动补位扩展padLeft、padRight实现代码
2020/04/06 Javascript
vue中defineProperty和Proxy的区别详解
2020/11/30 Vue.js
[07:09]2014DOTA2国际邀请赛-Newbee再次发威成功晋级决赛
2014/07/19 DOTA
[43:14]Liquid vs Optic 2018国际邀请赛淘汰赛BO3 第二场 8.21
2018/08/22 DOTA
用PyQt进行Python图形界面的程序的开发的入门指引
2015/04/14 Python
Python字符串格式化输出方法分析
2016/04/13 Python
python将ansible配置转为json格式实例代码
2017/05/15 Python
Python 实现购物商城,含有用户入口和商家入口的示例
2017/09/15 Python
关于Python 常用获取元素 Driver 总结
2019/11/24 Python
keras读取训练好的模型参数并把参数赋值给其它模型详解
2020/06/15 Python
Watchshop德国:欧洲在线手表No.1
2019/06/20 全球购物
英国最大的滑板品牌选择:Route One
2019/09/22 全球购物
2013年办公室秘书的个人自我鉴定
2013/10/24 职场文书
优秀英语专业毕业生求职信
2013/11/23 职场文书
会计电算化个人求职信范文
2014/01/24 职场文书
Nginx解决前端访问资源跨域问题的方法详解
2021/03/31 Servers
Rust中的Struct使用示例详解
2022/08/14 Javascript