1. 程式人生 > 其它 >vue-cropperjs 外掛的元件化使用

vue-cropperjs 外掛的元件化使用

vue-cropperjs 外掛的元件化使用

安裝

npm install --save vue-cropperjs   或者 cnpm install --save vue-cropperjs

區域性引入

import VueCropper from 'vue-cropperjs'
export default {
  components: { VueCropper },

元件內容

  <div>
    <div class="crop-demo">
      <div class="crop-demo-btn" v-show="false">
        點選更換圖片
        <input class="crop-input" type="file" name="image" accept="image/*" @change="setImage" id="change" />
      </div>
    </div>
    <el-dialog :append-to-body="true" title="圖片剪裁" :visible.sync="dialogVisible" :close-on-click-modal="false" width="40%">
      <vue-cropper :aspect-ratio="cropperAspectWH" ref="cropper" :src="imgSrc" :ready="cropImage" :zoom="cropImage" :cropmove="cropImage" style="width: 100%; height: 300px"></vue-cropper>
      <span slot="footer" class="dialog-footer">
        <el-button @click="cancelCrop">取 消</el-button>
        <el-button type="primary" @click="upladPic">確 定</el-button>
      </span>
    </el-dialog>
    <div v-show="false">{{ thisAspectWH }}</div>
  </div>
</template>
<script>
import VueCropper from 'vue-cropperjs'
export default {
  components: { VueCropper },
  props: ['label', 'AspectWH'],//label 是父元件傳的識別符號 (用於一個頁面內多處使用裁剪元件,裁剪結果返回值錯亂)   AspectWH 是用於限定裁剪框的比例的1為1:1  可傳null則是不限制(注意傳值是否為字串)
  data() {
    return {
      //以下都是截圖外掛的
      imgSrc: '',
      dialogVisible: false,
      img_size: '',
      max_fuyuan_defaultSrc: [],
      cropperAspectWH: 1, //圖片剪裁寬高比例
      reader: '',
      e_photo_file: '',
      e_photo_filefile: '',
      http_cropImg: '', //帶http
      cropImg: '', //預設圖片不帶http
    }
  },
  methods: {
    //監聽父元件是否點選上傳的事件
    childAction() {
      $('#change').click()
    },
    //向父元件傳送資料  cropImg 裁剪得到的圖片名稱  http_cropImg 帶域名的圖片名稱  label就是傳進來的識別符號,也帶著傳出去
    sendMsg() {
      this.$emit('getPicNamefile', this.cropImg, this.http_cropImg, this.label)
    },
    /******************************圖片剪下開始****************************************/
    setImage(e) {
      let that = this
      this.e_photo_file = e
      let file = e.target.files[0]
      this.e_photo_filefile = file
      if (!file.type.includes('image/')) {
        return
      }
      this.reader = ''
      let canvas = '',
        ctx = '',
        img = ''

      this.imgSrc = ''
      this.reader = new FileReader()
      this.reader.onload = (event) => {
        if (file.size >= 1024 * 1024 * this.GLOBAL.fileSize) {
          //呼叫自定義方法來處理圖片
          var quality = 1 //壓縮圖片的質量
          canvas = document.createElement('canvas') //建立畫布
          ctx = canvas.getContext('2d')
          img = new Image()
          img.src = event.target.result
          img.onload = function () {
            const width = img.width
            const height = img.height
            canvas.width = 1200 //這裡可以自定義你的圖片大小
            canvas.height = 1200 * (img.height / img.width)
            that.dialogVisible = true
            setTimeout(() => {
              ctx.fillRect(0, 0, 0, 0)
              ctx.drawImage(img, 0, 0, 1200, canvas.height)
              that.imgSrc = canvas.toDataURL('image/jpeg', quality) //將圖片轉為Base64 之後預覽要用
              that.$refs.cropper.replace(that.imgSrc)
            }, 50)
          }
        } else {
          that.dialogVisible = true
          that.$nextTick(function () {
            that.imgSrc = event.target.result
            that.$refs.cropper.replace(event.target.result)
          })
        }
      }
      that.reader.readAsDataURL(file)
    },
    setImage_two(e) {
      let that = this
      let file = this.e_photo_filefile
      let canvas = '', ctx = '',img = '';
      this.e_photo_file = e
      this.e_photo_filefile = file
      this.reader = ''
      this.imgSrc = ''
      this.reader = new FileReader()
      this.reader.onload = (event) => {
        //呼叫自定義方法來處理圖片
        var quality = 1 //壓縮圖片的質量
        canvas = document.createElement('canvas') //建立畫布

        ctx = canvas.getContext('2d')

        img = new Image()
        img.src = event.target.result
        img.onload = function () {
          // 清除畫布
          const width = img.width
          const height = img.height
          canvas.width = 1200 //這裡可以自定義你的圖片大小
          canvas.height = 1200 * (img.height / img.width)
          setTimeout(() => {
            ctx.fillRect(0, 0, 0, 0)
            ctx.drawImage(img, 0, 0, 1200, canvas.height)

            that.imgSrc = canvas.toDataURL('image/jpeg', quality) //將圖片轉為Base64 之後預覽要用
            that.$refs.cropper && that.$refs.cropper.replace(that.imgSrc)
          }, 50)
        }
      }
      that.reader.readAsDataURL(file)
    },
    cropImage() {
      this.http_cropImg = this.$refs.cropper.getCroppedCanvas().toDataURL()
    },
    cancelCrop() {
      this.dialogVisible = false
      this.http_cropImg = this.max_fuyuan_defaultSrc[this.max_fuyuan_defaultSrc.length - 1]
      $('#change').val('') //取消change事件
    },
    upladPic() {
      this.sumitImageFile(this.http_cropImg)
    },
    sumitImageFile(base64Codes) {
      let that = this
      var formData = new FormData()
      var picName = new Date().getTime() + '.png' //給截圖的檔案命名
      formData.append('file', that.convertBase64UrlToBlob(base64Codes), picName) //append函式的第一個引數是後臺獲取資料的引數名,和html標籤的input的name屬性功能相同

      if (this.img_size >= 1024 * 1024 * this.GLOBAL.fileSize) {
        this.$message({
          message: '要上傳圖片太大,請再次擷取,本次擷取將進行壓縮處理!',
          type: 'warning',
        })
        this.setImage_two(that.e_photo_file)
        return
      }
      if (this.img_size / 1024 / 1024 < this.GLOBAL.fileSize) {
        serviceApi.requestPostUploadFile(formData).then((body) => {
          that.cropImg = body.file_name
          //傳遞給父元件

          that.sendMsg()
        })
      } else {
        this.$message({
          message: '抱歉,要上傳圖片太大,請重新上傳!',
          type: 'warning',
        })
        that.cropImg = ''
        that.http_cropImg = ''
        //傳給表單
        //傳遞給父元件
        that.cropper_show = false
        that.sendMsg()
      }
      //關閉彈框
      $('#change').val('') //取消change事件
      this.dialogVisible = false
    },
    //將以base64的圖片url資料轉換為Blob
    convertBase64UrlToBlob(urlData) {
      var bytes = window.atob(urlData.split(',')[1]) //去掉url的頭,並轉換為byte
      //處理異常,將ascii碼小於0的轉換為大於0
      var ab = new ArrayBuffer(bytes.length)
      var ia = new Uint8Array(ab)
      for (let i = 0; i < bytes.length; i++) {
        ia[i] = bytes.charCodeAt(i)
      }
      let size = new Blob([ab], { type: 'image/png' })
      this.img_size = size.size
      return new Blob([ab], { type: 'image/png' })
    },
    /******************************圖片剪下結束****************************************/
  },
  computed: {
    thisAspectWH() {
      if (this.AspectWH) {
        this.cropperAspectWH = this.AspectWH
      }
    },
  },
  mounted() {
    //監聽父元件是否點選上傳的事件
    this.$on('inputfile', (val) => {
      if (this.AspectWH) {
        this.cropperAspectWH = this.AspectWH
      }
      this.childAction(val)
    })
  },
  watch: {},
  created() {
    if (this.AspectWH) {
      this.cropperAspectWH = this.AspectWH
    }
  },
}
</script>

<style scoped>
/* 圖片剪裁樣式 */
.crop-demo {
  display: flex;
  align-items: flex-end;
  width: 150px;
  height: 150px;
}
.crop-demo-btn {
  position: absolute;
  left: auto;
  top: 50%;
  transform: translateY(-50%);
  width: 100px;
  height: 40px;
  line-height: 40px;
  padding: 0;
  text-align: center;
  font-size: 12px;
  margin-left: 25px;
  color: #fff;
  background-color: rgba(0, 0, 0, 0.2);
  border-radius: 4px;
  box-sizing: border-box;
  cursor: pointer;
}
.crop-input {
  position: absolute;
  width: 100px;
  height: 40px;
  left: 0;
  top: 0;
  opacity: 0;
  font-size: 0;
  padding: 0;
  cursor: pointer;
}
</style>

注意點

這個方法要自己寫 serviceApi.requestPostUploadFile

父元件中使用

 <div class="crop-demo">
                <div
                  style="
                    position: relative;
                    display: flex;
                    width: 340px;
                    height: 170px;
                  "
                >
                  <span>
                    <img
                      :src="XXXXXXX"
                      style="
                        width: 340px;
                        height: 170px;
                        background: #f8f8f8;
                        border: 1px solid #eee;
                        border-radius: 5px;
                        object-fit: cover;
                      "
                    />
                  </span>
                  <div
                    style="
                      position: absolute;
                      left: 50%;
                      top: 50%;
                      transform: translate(-50%, -50%);
                      width: 100px;
                      line-height: 40px;
                      padding: 0;
                      text-align: center;
                      font-size: 12px;
                      background-color: #9da1a585;
                      color: #fff;
                      border-radius: 4px;
                      box-sizing: border-box;
                    "
                  >
                    點選更換圖片
                    <div
                      @click="toSonClick('label')"
                      style="
                        position: absolute;
                        width: 100px;
                        height: 40px;
                        left: 0;
                        top: 0;
                        opacity: 0;
                        cursor: pointer;
                      "
                    />
                  </div>
                </div>
              </div>
    <CropperCut
      v-if="CropperCutShow"
      :AspectWH="AspectWH"
      :label="CropperCutlabel"
      @getPicNamefile="getPicNamefile"
      ref="CropperCut"
    ></CropperCut>
    data中加入:
      //裁剪外掛的label   是誰呼叫的
      AspectWH: "1", //裁剪外掛的寬高比
      CropperCutlabel: "",
      CropperCutShow: false, //控制開關 裁剪外掛


  //裁剪外掛的事件
    toSonClick(label) {
      let that = this;
      if (label == "label") {
        this.AspectWH = 1;
      } else if (label == "XXX") {
        this.AspectWH = 2;
      }
      this.CropperCutShow = true;
      this.CropperCutlabel = label;
      setTimeout(() => {
        that.$refs.CropperCut.$emit("inputfile");
      }, 10);
    },
    //外掛外掛
    getPicNamefile(cropImg, http_cropImg, label) {
      this.CropperCutShow = false;
      this.AspectWH = 1;
      if (label == "label") {
        this.CropperCutlabel = "";
      } else if (label == "XXX") {
        this.CropperCutlabel = "";
      }
    },

**外掛官網:https://www.npmjs.com/package/vue-cropperjs