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
930 stars 128 forks source link

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

Closed GalacticHypernova closed 9 months ago

GalacticHypernova commented 9 months 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 9 months ago

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

GalacticHypernova commented 9 months 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 9 months 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 9 months ago

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

GalacticHypernova commented 9 months 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 9 months 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 9 months 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 9 months 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 9 months 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 9 months ago

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

Norserium commented 9 months ago

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

@GalacticHypernova, that's it.

GalacticHypernova commented 9 months ago

Thank you!

Norserium commented 9 months ago

@GalacticHypernova, you are welcome!