cropper.js 패키지 vue 기반 온라인 이미지 재단 구성 요소 기능 구현

효과 도 는 다음 과 같다.

github:demo 다운로드
cropper.js
github:cropper.js
홈 페이지(demo)
cropper.js 설치
  • npm 또는 bower 설치
  • 
    npm install cropper
    # or
    bower install cropper
    clone 다운로드:다운로드 주소
    git clone https://github.com/fengyuanchen/cropper.git
    cropper.js 참조
    주로 cropper.js 와 cropper.css 두 파일 을 참조 합 니 다.
    
    <script src="/path/to/jquery.js"></script><!-- jQuery is required -->
    <link href="/path/to/cropper.css" rel="external nofollow" rel="stylesheet">
    <script src="/path/to/cropper.js"></script>
    메모:jquery 파일 을 먼저 도입 해 야 cropper.js 플러그 인 을 사용 할 수 있 습 니 다.
    간단히 사용 하 다
    캡 처 에 사용 할 div 용기 구축
    
    <!-- Wrap the image or canvas element with a block element (container) -->
    <div>
     ![](picture.jpg)
    </div>
    용기 의 스타일 을 추가 하여 img 을 전체 용기 에 채 우 는 것 이 중요 합 니 다(중요 합 니 다)
    
    /* Limit image width to avoid overflow the container */
    img {
     max-width: 100%; /* This rule is very important, please do not ignore this! */
    }
    cropper.js 방법 을 호출 하여 캡 처 컨트롤 을 초기 화 합 니 다.
    
    $('#image').cropper({
     aspectRatio: 16 / 9,
     crop: function(e) {
     // Output the result data for cropping image.
     console.log(e.x);
     console.log(e.y);
     console.log(e.width);
     console.log(e.height);
     console.log(e.rotate);
     console.log(e.scaleX);
     console.log(e.scaleY);
     }
    });
    기타 상세 api 참조:github:cropper.js
    vue 구성 요소 로 밀봉
    vue 구성 요소 로 봉 인 된 문제
  • cropper.js 관련
  • 아 날로 그 input 상 자 를 누 르 면 그림 을 선택 하고 선택 한 그림 의 형식,크기 제한 을 합 니 다.
    그림 재단 다시 선택
    재단 을 확인 하고 base 64 형식의 그림 정 보 를 가 져 옵 니 다.
  • vue 관련
  • 비 부자 구성 요소 간 통신 문제
    아 날로 그 input 상 자 를 누 르 면 그림 을 선택 하고 선택 한 그림 의 형식,크기 제한 을 합 니 다.
    숨겨 진 input 탭 을 만 들 고 이 input 를 모 의 클릭 하여 그림 을 선택 할 수 있 는 기능 을 수행 합 니 다.
    
    <!-- input  -->
    <input id="myCropper-input" type="file" :accept="imgCropperData.accept" ref="inputer" @change="handleFile">
    //    
    document.getElementById('myCropper-input').click();
    input 에 감청 내용 의 변 화 를 연결 하 는 방법 으로 업 로드 된 파일 을 가 져 오고 형식,크기 검 사 를 실시 합 니 다.
    
    // imgCropperData: {
    // accept: 'image/gif, image/jpeg, image/png, image/bmp',
    // }
    handleFile (e) {
     let _this = this;
     let inputDOM = this.$refs.inputer;
     //   DOM     
     _this.file = inputDOM.files[0];
     //       
     if (_this.imgCropperData.accept.indexOf(_this.file.type) == -1) {
     _this.$Modal.error({
      title: '    ',
      content: '           !'
     });
     return;
     }
     //         
     if (_this.file.size > 5242880) {
     _this.$Modal.error({
      title: '    ',
      content: '        ,   5MB     !'
     });
     return;
     }
     var reader = new FileReader();
     //        base64   
     reader.readAsDataURL(_this.file);
     reader.onload = function () {
     _this.imgCropperData.imgSrc = this.result;
     _this.initCropper();
     }
    }
    그림 재단 다시 선택
    처음 그림 을 선택 한 후에 그림 을 다시 선택해 야 하 는 문제 에 직면 하 게 될 것 입 니 다.그러면 재단 상자 에 있 는 그림 을 어떻게 교체 하 는 지 에 직면 하 게 될 것 입 니 다.위의 절 차 는 그림 을 선택 한 후에FileRender()방법 으로 그림 의 주요 정 보 를 얻 었 습 니 다.지금 은 재단 상 자 를 다시 구축 하면 문 제 를 해결 할 수 있 습 니 다.cropper.js 가 제시 한공식 데모을 살 펴 보 세 요.공식 적 으로 는 동적 으로 용 기 를 자 르 는 방법 을 추가 하여 조작 한 것 으로 밝 혀 졌 으 며,여기 서 우 리 는 공식 적 으로 이 루어 졌 다.
    
    //      
     initCropper () {
     let _this = this;
     //        
     _this.imgObj = $('![](' + _this.imgCropperData.imgSrc + ')');
     let $avatarPreview = $('.avatar-preview');
     $('#myCropper-workspace').empty().html(_this.imgObj);
     _this.imgObj.cropper({
      aspectRatio: _this.proportionX / _this.proportionY,
      preview: $avatarPreview,
      crop: function(e) {
    
      }
     });
     }
    재단 을 확인 하고 base 64 형식의 그림 정 보 를 가 져 옵 니 다.
    
    let $imgData = _this.imgObj.cropper('getCroppedCanvas')
    imgBase64Data = $imgData.toDataURL('image/png');
    업로드 에 사용 할 데 이 터 를 구성 합 니 다.
    
    //          
    let formData = new FormData();
    //      
    let photoType = imgBase64Data.substring(imgBase64Data.indexOf(",") + 1);
    //    
    const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => {
     const byteCharacters = atob(b64Data);
     const byteArrays = [];
     for(let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
     const slice = byteCharacters.slice(offset, offset + sliceSize);
     const byteNumbers = new Array(slice.length);
     for(let i = 0; i < slice.length; i++) {
      byteNumbers[i] = slice.charCodeAt(i);
     }
     const byteArray = new Uint8Array(byteNumbers);
     byteArrays.push(byteArray);
     }
     const blob = new Blob(byteArrays, {
     type: contentType
     });
     return blob;
    }
    const contentType = 'image/jepg';
    const b64Data2 = photoType;
    const blob = b64toBlob(b64Data2, contentType);
    formData.append("file", blob, "client-camera-photo.png")
    formData.append("type", _this.imgType)
    비 부자 구성 요소 간 통신 문제
    이전 항목 에 서 는 부자 구성 요소 간 의 통신 인삼 을 자주 사용 하 며,일반적으로 두 가지 방법 을 사용한다.
    router 에 파 라 메 터 를 설치 한 후 route.params.xxx 또는 route.query.xxx 를 호출 하여 가 져 옵 니 다.
    props 를 통 해 통신 하 다
    여기 서 이벤트 버스 를 사용 하여 구성 요소 간 의 통신 을 진행 합 니 다.
    순서
    1.bus 구성 요 소 는 B 구성 요소 가 A 구성 요소 에 인 자 를 전달 하 는 데 사 용 됩 니 다.
    
    //bus.js
    import Vue from 'vue'; 
    export default new Vue();
    2.A 구성 요소 에서 bus 구성 요 소 를 참조 하고 매개 변수 변 화 를 실시 간 으로 감청 합 니 다.
    
    // A.vue
    import Bus from '../../components/bus/bus.js'
    export default {
     components: { Bus },
     data () {},
     created: function () {
     Bus.$on('getTarget', imgToken => { 
      var _this = this;
      console.log(imgToken);
      ... 
     }); 
     }
    }
    3.B 구성 요소 에서 도 bus 구성 요 소 를 참조 하여 인 자 를 A 구성 요소 에 전달 합 니 다.
    
    // B.vue
    //   
    Bus.$emit('getTarget', imgToken);
    참고:
    vue-$on
    vue-$emit
    vue.js 의 길(4)-vue 2.0 s 에서 eventBus 는 형제 구성 요소 통신 을 실현 합 니 다.
    vue 선택 캡 처 플러그 인 전체 코드
    
    <template>
     <div class="myCropper-container">
     <div id="myCropper-workspace">
      <div class="myCropper-words" v-show="!imgCropperData.imgSrc">             </div>
     </div>
     <div class="myCropper-preview" :class="isShort ? 'myCropper-preview-short' : 'myCropper-preview-long'">
      <div class="myCropper-preview-1 avatar-preview">
      ![](!imgCropperData.imgUploadSrc ? '/images/thumbnail/thumbnail-img.jpg' : imgCropperData.imgUploadSrc)
      </div>
      <div class="myCropper-preview-2 avatar-preview">
      ![](!imgCropperData.imgUploadSrc ? '/images/thumbnail/thumbnail-img.jpg' : imgCropperData.imgUploadSrc)
      </div>
      <div class="myCropper-preview-3 avatar-preview">
      ![](!imgCropperData.imgUploadSrc ? '/images/thumbnail/thumbnail-img.jpg' : imgCropperData.imgUploadSrc)
      </div>
      <input id="myCropper-input" type="file" :accept="imgCropperData.accept" ref="inputer" @change="handleFile">
      <Button type="ghost" class="myCropper-btn" @click="btnClick">    </Button>
      <Button type="primary" class="myCropper-btn" :loading="cropperLoading" @click="crop_ok">  </Button>
     </div>
     </div>
    </template>
    <script>
     var ezjsUtil = Vue.ezjsUtil;
     import Bus from './bus/bus.js' 
     export default {
     components: { Bus },
     props: {
      imgType: {
      type: String
      },
      proportionX: {
      type: Number
      },
      proportionY: {
      type: Number
      }
     },
     data () {
      return {
      imgCropperData: {
       accept: 'image/gif, image/jpeg, image/png, image/bmp',
       maxSize: 5242880,
       file: null, //     
       imgSrc: '', //   img  base64   
       imgUploadSrc: '', //     img  base64   
      },
      imgObj: null,
      hasSelectImg: false,
      cropperLoading: false,
      isShort: false,
      }
     },
     created: function () {
      let _this = this;
     },
     mounted: function () {
      let _this = this;
      //        
      let maxWidthNum = Math.floor(300 / _this.proportionX);
      let previewWidth = maxWidthNum * _this.proportionX;
      let previewHeight = maxWidthNum * _this.proportionY;
      if (previewWidth / previewHeight <= 1.7) {
      previewWidth = previewWidth / 2;
      previewHeight = previewHeight / 2;
      _this.isShort = true;
      }
      //            
      $('.myCropper-preview-1').css('width', previewWidth + 'px');
      $('.myCropper-preview-1').css('height', previewHeight + 'px');
      //            
      $('.myCropper-container .myCropper-preview .myCropper-preview-2').css('width',( previewWidth / 2) + 'px');
      $('.myCropper-container .myCropper-preview .myCropper-preview-2').css('height', (previewHeight / 2) + 'px');
      //            
      $('.myCropper-container .myCropper-preview .myCropper-preview-3').css('width',( previewWidth / 4) + 'px');
      $('.myCropper-container .myCropper-preview .myCropper-preview-3').css('height', (previewHeight / 4) + 'px');
     },
     methods: {
      //       
      btnClick () {
      let _this = this;
      //   input      
      document.getElementById('myCropper-input').click();
      },
      //        
      handleFile (e) {
      let _this = this;
      let inputDOM = this.$refs.inputer;
      //   DOM     
      _this.file = inputDOM.files[0];
      //       
      if (_this.imgCropperData.accept.indexOf(_this.file.type) == -1) {
       _this.$Modal.error({
       title: '    ',
       content: '           !'
       });
       return;
      }
      //         
      if (_this.file.size > 5242880) {
       _this.$Modal.error({
       title: '    ',
       content: '        ,   5MB     !'
       });
       return;
      }
      var reader = new FileReader();
      //        base64   
      reader.readAsDataURL(_this.file);
      reader.onload = function () {
       _this.imgCropperData.imgSrc = this.result;
       _this.initCropper();
      }
      },
      //      
      initCropper () {
      let _this = this;
      //        
      _this.imgObj = $('![](' + _this.imgCropperData.imgSrc + ')');
      let $avatarPreview = $('.avatar-preview');
      $('#myCropper-workspace').empty().html(_this.imgObj);
      _this.imgObj.cropper({
       aspectRatio: _this.proportionX / _this.proportionY,
       preview: $avatarPreview,
       crop: function(e) {
       }
      });
      _this.hasSelectImg = true;
      },
      //   
      crop_ok () {
      let _this = this, imgToken = null, imgBase64Data = null;
      //         
      if (_this.hasSelectImg == false) {
       _this.$Modal.error({
       title: '    ',
       content: '     ,        !'
       });
       return false;
      }
      //        
      _this.cropperLoading = true;
      let $imgData = _this.imgObj.cropper('getCroppedCanvas')
      imgBase64Data = $imgData.toDataURL('image/png'); 
      //          
      let formData = new FormData();
      //      
      let photoType = imgBase64Data.substring(imgBase64Data.indexOf(",") + 1);
      //    
        const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => {
         const byteCharacters = atob(b64Data);
         const byteArrays = [];
         for(let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
          const slice = byteCharacters.slice(offset, offset + sliceSize);
          const byteNumbers = new Array(slice.length);
          for(let i = 0; i < slice.length; i++) {
           byteNumbers[i] = slice.charCodeAt(i);
          }
          const byteArray = new Uint8Array(byteNumbers);
          byteArrays.push(byteArray);
         }
         const blob = new Blob(byteArrays, {
          type: contentType
         });
         return blob;
      }
      const contentType = 'image/jepg';
        const b64Data2 = photoType;
      const blob = b64toBlob(b64Data2, contentType);
      formData.append("file", blob, "client-camera-photo.png")
      formData.append("type", _this.imgType)
      // ajax  
      $.ajax({
         url: _this.$nfs.uploadUrl,
         method: 'POST',
         data: formData,
         //    true,  false   ajax    (      )     $.ajax(...)     
         async: false,
         //     ,      FormData    ,contentType     ,    jquery         (   )。
         cache: false,
         contentType: false,
       processData: false,
       type: _this.imgType,
         success: function(res) {
       let imgToken = res.data.token;
       _this.cropperLoading = false;
       //   
       Bus.$emit('getTarget', imgToken); 
         },
         error: function(error) {
       _this.cropperLoading = false;
       _this.$Modal.error({
        title: '    ',
        content: '           !'
       });
         }
        });
      },
     }
     }
    </script>
    <style lang="less" scoped>
     .myCropper-container {
     height: 400px;
     }
     .myCropper-container #myCropper-input {
     width: 0px;
     height: 0px;
     }
     .myCropper-container #myCropper-workspace {
     width: 500px;
     height: 400px;
     border: 1px solid #dddee1;
     float: left;
     }
     //               
     .myCropper-container #myCropper-workspace .myCropper-words{
     text-align: center;
     font-size: 18px;
     padding-top: 180px;
     }
     //          
     .myCropper-container .myCropper-preview-long {
     width: 300px;
     }
     .myCropper-container .myCropper-preview-short {
     width: 200px;
     }
     .myCropper-container .myCropper-preview {
     float: left;
     height: 400px;
     margin-left: 10px;
     }
     .myCropper-container .myCropper-preview .myCropper-preview-1 {
     border-radius: 5px;
     overflow: hidden;
     border: 1px solid #dddee1;
     box-shadow: 3px 3px 3px #dddee1;
     img {
      width: 100%;
      height: 100%;
     }
     }
     .myCropper-container .myCropper-preview .myCropper-preview-2 {
     margin-top: 20px;
     border-radius: 5px;
     overflow: hidden;
     border: 1px solid #dddee1;
     box-shadow: 3px 3px 3px #dddee1;
     img {
      width: 100%;
      height: 100%;
     }
     }
     .myCropper-container .myCropper-preview .myCropper-preview-3 {
     margin-top: 20px;
     border-radius: 5px;
     overflow: hidden;
     border: 1px solid #dddee1;
     box-shadow: 3px 3px 3px #dddee1;
     img {
      width: 100%;
      height: 100%;
     }
     }
     //   
     .myCropper-btn {
     float: left;
     margin-top: 20px;
     margin-right: 10px;
     }
    </style>
    BY-LucaLJX
    github: lucaljx
    총결산
    위 에서 말 한 것 은 소 편 이 소개 한 cropper.js 패키지 vue 를 바탕 으로 온라인 이미지 재단 구성 요소 기능 을 실현 하 는 것 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 메 시 지 를 남 겨 주세요.소 편 은 제때에 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

    좋은 웹페이지 즐겨찾기