zoukankan      html  css  js  c++  java
  • 利用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 {
           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 {
         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'
              })
            }
          })
        })
    },
  • 相关阅读:
    luogu P1955 [NOI2015]程序自动分析
    luogu P5514 [MtOI2019]永夜的报应
    bzoj1816[Cqoi2010]扑克牌
    bzoj1040[ZJOI2008]骑士
    bzoj4582[Usaco2016 Open]Diamond Collector
    bzoj1029[JSOI2007]建筑抢修
    bzoj1079[SCOI2008]着色方案
    bzoj1051[HAOI2006]受欢迎的牛
    bzoj4525[Usaco2016 Jan]Angry Cows
    bzoj4512[Usaco2016 Jan] Build Gates
  • 原文地址:https://www.cnblogs.com/goloving/p/9721261.html
Copyright © 2011-2022 走看看