Search code examples
javascriptvue.jscropperjsvue-dropzone

I get the error when i try get 50% of the image with cropperJS


I want to get 50% of the image with 'cropperJS'. I create a new Image() and try to create new Cropper for further obtaining canvas. And I get the error 'Cannot read property 'insertBefore' of null', please help me to solve this problem. Or show me how can i get 50% of the image with out 'cropperJS'. Thanks in advance.

<template>
  <v-layout
    column
    justify-center
    align-center
  >
    <v-flex
      xs12
      sm8
      md6
    >
    <vue-dropzone 
      ref="myVueDropzone" 
      id="dropzone" 
      :options="dropzoneOptions"
      @vdropzone-success="vdropzoneSuccess"
    >
    </vue-dropzone>
    <v-img 
      :src="imgUrl" 
    >
    </v-img>
    </v-flex>
  </v-layout>
</template>

<script>
import Logo from '~/components/Logo.vue'
import VuetifyLogo from '~/components/VuetifyLogo.vue'
import vue2Dropzone from 'vue2-dropzone'
import 'vue2-dropzone/dist/vue2Dropzone.min.css'
import Cropper from 'cropperjs'

export default {
  data: function () {
    return {
      imgUrl:'',
      dropzoneOptions: {
          url: 'https://httpbin.org/post',
          thumbnailWidth: 150,
          maxFilesize: 0.5,
          headers: { "My-Awesome-Header": "header value" }
      }
    }
  },
  components: {
    vueDropzone: vue2Dropzone
  },
  methods:{
    vdropzoneSuccess(file, response){
      this.imgUrl = file.dataURL
      var image = new Image()
      image.src = URL.createObjectURL(file)
      console.log(image)
      var cropper = new Cropper(image, {
        aspectRatio: 16 / 9,
        crop(event) {
          console.log(event.detail.x)
          console.log(event.detail.y)
          console.log(event.detail.width)
          console.log(event.detail.height)
        },
      })
      console.log(cropper)
    }
  }
}
</script>

Solution

  • First off Cropper.js accepts DOM node as the first param, so you sould pass the DOM node. Following the documentation, this DOM node should be wrapped in <div></div>. Only when image is loaded, should you init the Cropper.js.

    <template>
      <v-layout
        column
        justify-center
        align-center
      >
        <v-flex
          xs12
          sm8
          md6
        >
        <vue-dropzone 
          ref="myVueDropzone" 
          id="dropzone" 
          :options="dropzoneOptions"
          @vdropzone-success="vdropzoneSuccess"
        >
        </vue-dropzone>
        <div>
          <img
            ref="img"
            :src="imgUrl" 
          />
        </div>
        </v-flex>
      </v-layout>
    </template>
    
    <script>
      import Logo from '~/components/Logo.vue'
      import VuetifyLogo from '~/components/VuetifyLogo.vue'
      import vue2Dropzone from 'vue2-dropzone'
      import 'vue2-dropzone/dist/vue2Dropzone.min.css'
      import Cropper from 'cropperjs'
    
      export default {
        data: function() {
          return {
            imgUrl: '',
            dropzoneOptions: {
              url: 'https://httpbin.org/post',
              thumbnailWidth: 150,
              maxFilesize: 0.5,
              headers: {
                "My-Awesome-Header": "header value"
              }
            }
          }
        },
        components: {
          vueDropzone: vue2Dropzone
        },
        methods: {
          vdropzoneSuccess(file, response) {
            this.imgUrl = file.dataURL
            var image = new Image()
            image.src = URL.createObjectURL(file)
            image.onload = () => {
              var cropper = new Cropper(this.$refs.img, {
                aspectRatio: 16 / 9,
                crop(event) {
                  console.log(event.detail.x)
                  console.log(event.detail.y)
                  console.log(event.detail.width)
                  console.log(event.detail.height)
                },
              })
            }
    
          }
        }
      }
    </script>