advanced-cropper / vue-advanced-cropper

The advanced vue cropper library that gives you opportunity to create your own croppers suited for any website design
https://advanced-cropper.github.io/vue-advanced-cropper/
Other
1.01k stars 136 forks source link

Usage of the cropper in Composition API through a composable/util #251

Closed GalacticHypernova closed 1 year ago

GalacticHypernova commented 1 year ago

This isn't a bug, it's just a question: In a Nuxt 2.x application using a cropper through a mixin in the ~/mixins folder works fine, and I am able to import it from the mixins folder for use throughout multiple pages, but how does it change in composition API? Does it follow the same convention as vue's defineComponent virtual code with the components, data, and methods? How should the code change in order to account for this new format? If needed, I will gladly share the code I have, as this is a very useful tool for my app, and I'd like a bit of help to migrate it to Composition API.

Norserium commented 1 year ago

@GalacticHypernova, the using of mixins for the cropper sounds like an unusual idea. Could you provide the code?

GalacticHypernova commented 1 year ago

Of course. This is the code that was used in the v2.x application (located in ~/mixins, moved to ~/composables in the Nuxt 3.x application):

import { Cropper } from 'vue-advanced-cropper'

export default {
  components: {
    Cropper
  },
  data: () => ({
    isDragOver: false,
    selectedImage: false,
    imgErr: '',
    imgUrl: '',
    croppedImg: '',
    cropDone: false
  }),
  methods: {
    dragover (e) {
      this.isDragOver = true
    },
    dragFinish () {
      this.isDragOver = false
    },
    preview (e) {
      this.imgErr = ''
      const file = e.target.files[0]
      if (file) {
        this.cropDone = false
        this.selectedImage = true
        this.imgUrl = URL.createObjectURL(file)
      }
    },
    editCrop () {
      this.cropDone = false
    },
    cropEnd (e) {
      const { canvas } = e
      const dataURL = canvas.toDataURL('image/webp')
      this.croppedImg = dataURL
    },
    saveCrop () {
      this.$refs.thumbnailImg.src = this.croppedImg
      this.cropDone = true
    },
    cancelImage () {
      this.selectedImage = false
      this.imgUrl = ''
      this.croppedImg = ''
    },
    dropFile (e) {
      this.isDragOver = false
      const file = e.dataTransfer.files[0]
      if (file) {
        this.cropDone = false
        this.selectedImage = true
        this.imgUrl = URL.createObjectURL(file)
      }
    }
  }
}
GalacticHypernova commented 1 year ago

The reason it's in a mixin is because it's being used throughout multiple pages, so in stead of adding it to all pages that use it, it was placed in mixins in stead, and then all there was to do was just importing it.

Norserium commented 1 year ago

@GalacticHypernova, why do you use the mixin instead of creating the wrapper for Cropper component?

GalacticHypernova commented 1 year ago

Hey @Norserium , just pinging you in case you didn't see my response as I had accidentally predicted the question before you actually asked it (at least on my screen).

Norserium commented 1 year ago

@GalacticHypernova, well, but if you create the wrapper component you get the opportunity to reuse it on multiple pages. It look like more idiomatic approach.

Norserium commented 1 year ago

Anyway, you can easily rewrite your mixin to a composable function. There is nothing specific to this library.

That's the result of artificial intelligence work. I didn't check it, but it looks right.

import { ref } from 'vue';

export function useCropper() {
    const isDragOver = ref(false);
    const selectedImage = ref(false);
    const imgErr = ref('');
    const imgUrl = ref('');
    const croppedImg = ref('');
    const cropDone = ref(false);

    const dragover = () => {
      isDragOver.value = true;
    };

    const dragFinish = () => {
      isDragOver.value = false;
    };

    const preview = (e) => {
      imgErr.value = '';
      const file = e.target.files[0];
      if (file) {
        cropDone.value = false;
        selectedImage.value = true;
        imgUrl.value = URL.createObjectURL(file);
      }
    };

    const editCrop = () => {
      cropDone.value = false;
    };

    const cropEnd = (e) => {
      const { canvas } = e;
      const dataURL = canvas.toDataURL('image/webp');
      croppedImg.value = dataURL;
    };

    const saveCrop = () => {
      // Assuming that you have a ref called 'thumbnailImg' for the image element.
      thumbnailImg.value.src = croppedImg.value;
      cropDone.value = true;
    };

    const cancelImage = () => {
      selectedImage.value = false;
      imgUrl.value = '';
      croppedImg.value = '';
    };

    const dropFile = (e) => {
      isDragOver.value = false;
      const file = e.dataTransfer.files[0];
      if (file) {
        cropDone.value = false;
        selectedImage.value = true;
        imgUrl.value = URL.createObjectURL(file);
      }
    };

    return {
      isDragOver,
      selectedImage,
      imgErr,
      imgUrl,
      croppedImg,
      cropDone,
      dragover,
      dragFinish,
      preview,
      editCrop,
      cropEnd,
      saveCrop,
      cancelImage,
      dropFile,
    };
};
GalacticHypernova commented 1 year ago

Thanks, I will try that. I know using it as a component would probably be best but there are a couple of differences in the use cases in terms of elements and such so I wanted to get it working first, and later I could probably rewrite it once I figure out the best way to implement it.

GalacticHypernova commented 1 year ago

Would I not need to import the Cropper as well? Or is that done from the places where I actually use the cropper?

GalacticHypernova commented 1 year ago

I'll close this for now, to make my testing, and if anything I'll reopen. Thanks for the help!

Norserium commented 1 year ago

Or is that done from the places where I actually use the cropper?

@GalacticHypernova, that's it.

GalacticHypernova commented 1 year ago

Thank you!

Norserium commented 1 year ago

@GalacticHypernova, you are welcome!