利用vue-cropper作的關於圖片裁剪、壓縮、上傳、預覽等作的一個公共組件

  公共組件:vue

<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>

  調用canvas

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

  注意下面這個二進制文件接收和上傳的問題app

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' }) } }) }) },
相關文章
相關標籤/搜索