利用vue-cropper做的关于图片裁剪、压缩、上传、预览等做的一个公共组件


  公共组件:

<template>
  <div>
    <div class="upload-box">
      <div class="image-box" v-if="imageUrl" :style="{'background-image': 'url('+ imageUrl +')', 'height': imageHeight}"></div>
      <div class="upload">
        <h6 class="upload-des">支持 jpg、png 格式大小 5M 以内的图片</h6>
        <input type="file" @change="getFile" ref="file" id="file">
        <label for="file">点击上传</label>
      </div>
    </div>
    <!-- vueCropper 剪裁图片实现-->
    <div class="vue-cropper-box" v-if="isShowCropper">
      <div class="vue-cropper-content">
        <vueCropper ref="cropper" :img="option.img" :outputSize="option.outputSize" :outputType="option.outputType" :info="option.info" :canScale="option.canScale" :autoCrop="option.autoCrop" :autoCropWidth="option.autoCropWidth" :autoCropHeight="option.autoCropHeight" :fixed="option.fixed" :fixedNumber="option.fixedNumber">
        </vueCropper>
      </div>
    </div>
    <el-button v-if="isShowCropper" type="danger" @click="onCubeImg">确定裁剪图片</el-button>
  </div>
</template>
<script> import VueCropper from "vue-cropper" export default { name: 'Avatar', data () { return { //裁剪组件的基础配置option
 option: { img: '', //裁剪图片的地址
          info: true, //裁剪框的大小信息
          outputSize: 1, // 裁剪生成图片的质量
          outputType: 'png', //裁剪生成图片的格式
          canScale: false, // 图片是否允许滚轮缩放
          autoCrop: true, // 是否默认生成截图框
          autoCropWidth: 195, // 默认生成截图框宽度
          autoCropHeight: 10, // 默认生成截图框高度
          fixed: false, //是否开启截图框宽高固定比例
          fixedNumber: [1, 1] //截图框的宽高比例
 }, isShowCropper: false //是否显示截图框
 } }, props: { // 特殊配置
 cropperOption: { type: Object, default: () => { return null } }, // 默认图片
 imageUrl: { type: String, default: '' }, // 图片展示高度
 imageHeight: { type: String, default: '100px' } }, components: { VueCropper }, methods: { getFile (e) { let _this = this
        var files = e.target.files[0] if (!e || !window.FileReader) return // 看支持不支持FileReader
        let reader = new FileReader() reader.readAsDataURL(files) reader.onloadend = function () { _this.isShowCropper = true _this.option.img = this.result _this.$refs.file.value = '' } }, // 确定裁剪图片
 onCubeImg () { this.$refs.cropper.getCropData((data) => { this.isShowCropper = false
          //console.log("压缩前的图片大小:" + data.length)
          let img = new Image(), _this = this img.src = data img.onload = function() { //let _data = _this.compress(img)
            let blob = _this.dataURItoBlob(data) let formData = new FormData() formData.append("icon", blob) //console.log("将blob对象转成formData对象:" + formData.get("icon"))
            _this.$emit('cropped', data, formData) } }) }, // 压缩图片 
 compress(img) { let canvas = document.createElement("canvas"), ctx = canvas.getContext("2d"), initSize = img.src.length, width = img.width, height = img.height; canvas.width = width canvas.height = height // 铺底色 
        ctx.fillStyle = "#fff" ctx.fillRect(0, 0, canvas.width, canvas.height) ctx.drawImage(img, 0, 0, width, height) //进行压缩 
        let ndata = canvas.toDataURL("image/jpeg", 0.8) //console.log("压缩后的图片大小:" + ndata.length)
        return ndata }, // base64转成bolb对象 
 dataURItoBlob(base64Data) { let byteString if (base64Data.split(",")[0].indexOf("base64") >= 0) byteString = atob(base64Data.split(",")[1]) else byteString = unescape(base64Data.split(",")[1]) let mimeString = base64Data .split(",")[0] .split(":")[1] .split(";")[0]; let ia = new Uint8Array(byteString.length); for (let i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); } return new Blob([ia], { type: mimeString }) }, // 初始化配置文件
 initOptions () { this.isShowCropper = false
        if (this.cropperOption) { for (let key in this.option) { this.option[key] = this.cropperOption[key] || this.option[key] } } } }, created () { this.initOptions() } } </script>
<style scoped lang="stylus" rel="stylesheet"> .upload-box { & > div { display inline-block vertical-align middle } & .upload-des { margin 0 font-weight 400 color #909399 } } .image-box { width 100px height 100px margin-right 20px background-size 100px auto background-position left center background-repeat no-repeat } .upload { & label { width: 80px; height: 24px; font-size: 12px; line-height: 24px; display: inline-block; border-radius: 4px; text-align: center; border: 1px solid #ddd; cursor pointer } } input[type='file'] { display: none; } .vue-cropper-box { width: 60%; height: 200px; margin: 15px 0px; .vue-cropper-content { height 200px } } </style>

  调用

<el-form-item label="头像" prop="icon" :rules="rules.required">
  <Avatar v-on:cropped="doCrop"   :cropperOption="cropperOption"   :imageUrl="guestInfo.icon"></Avatar>
</el-form-item>

  注意下面这个二进制文件接收和上传的问题

resetForm(){   this.$nextTick(() => {     this.$refs.guest.clearValidate()     this.guestUpInfo = new FormData()   }) },
//完成裁剪
doCrop(icon, file){   this.guestInfo.icon = icon   this.guestUpInfo = file }
//新增、编辑提交
submitGuest(){ validCallback(this, 'guest', () => { this.guestUpInfo.append('name',this.guestInfo.name) this.guestUpInfo.append('position',this.guestInfo.position) this.guestUpInfo.append('description',this.guestInfo.description) if(this.guestInfo.seq){ this.guestUpInfo.append('seq',this.guestInfo.seq) } if(this.editGuest){ this.guestUpInfo.append('id',this.guestInfo.id) } publicSubmitApi('saveSpeaker', this.guestUpInfo, true).then(res => { if (res.status === 200) { this.guestShow = false
          this.fetchData() this.$message({ message: this.editGuest ? '编辑成功' : '新增成功', type: 'success' }) } }) }) },

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM