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
931 stars 130 forks source link

vstencil-component example not working in vue3 #168

Closed MarisKay closed 2 years ago

MarisKay commented 2 years ago

Please update this for Vue v3, so ppl know how to use it! Currently not working the way it is presented. Thank you!

<div id="app">
  <cropper
    src="https://images.pexels.com/photos/1254140/pexels-photo-1254140.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"
    :stencil-component="$options.components.CircleStencil"
  />
</div>

Gives error : The "CircleStencil" component has been registered but not used

Norserium commented 2 years ago

@MarisKay, it's not a Vue 3 issue.

It's the issue of ESLint. It can't detect that this component is actually used (the relevant issue).

You can bypass it by:

  1. Ignoring this rule for CircleStencil;
  2. Passing the component to setup or data instead of components:
    setup() {
    return {
       CircleStencil
     }
    }

    After that you can write:

    <cropper :stencil-component="CircleStencil" />
Norserium commented 2 years ago

I've created the sandbox example for you.

Norserium commented 2 years ago

@MarisKay, any news?

MarisKay commented 2 years ago

Okay, now i see! Thank you. In your example though the cropped result looks still squarish. Doesn't the cropper apply the stencil to the final result? Like shouldn't it be a cropped circle image when it crops and presents the result?

Norserium commented 2 years ago

@MarisKay, no it shouldn't. But you can crop it himself if it's needed. Usually it's not.

MarisKay commented 2 years ago

and now since i used: import {Cropper, CircleStencil} from "vue-advanced-cropper"

export default {
  components: {
    Cropper,
  },
  data() {
    return {
      CircleStencil,
    }
  },

and in template:

        <cropper v-show="imageInCanvas"
                 ref="cropper"
                 min-width="200"
                 class="cropper"
                 :src="image.src"
                 :stencil-component="(isRound===true? CircleStencil : RectangleStencil)"
                 :stencil-props="{
              aspectRatio: aspectRatio,
              movable: true,
              resizable: true
            }"
        />

i started to get this kind of error:

runtime-core.esm-bundler.js?9e79:6620 [Vue warn]: Vue received a Component which was made a reactive object. This can lead to unnecessary performance overhead, and should be avoided by marking the component with markRaw or using shallowRef instead of ref.

Removing one single line from template stops it, but i lose the stencil:

:stencil-component="(isRound===true? CircleStencil : RectangleStencil)"

Please advise, i am using options api! Thanks

MarisKay commented 2 years ago

No idea whether this is the correct solution, but i have added:

  mounted() {
    this.CircleStencil = Object.freeze(CircleStencil)
    this.RectangleStencil = Object.freeze(RectangleStencil)
  },

and the problem vanished. Let me know if there's a more proper way doing this. Thanks

Norserium commented 2 years ago

@MarisKay, well there are a plenty of options except those that I suggested earlier.

  1. You can mark raw your component to eliminate that warning and potential performance issues:

    data() {
    return {
      CircleStencil: markRaw(CircleStencil)
    };
    },
  2. You can define CircleStencil and RectangleStencil in created hook. It definitely makes more sense.

    created() {
    this.CircleStencil = CircleStencil;
    this.RectangleStencil = RectangleStencil;
    },
  3. But the best option in your case that would be fit in your case perfectly (in my opinion) is the defining stencilComponent property in the computed section:

    computed: {
    stencilComponent() {
         return this.isRound ? CircleStencil : RectangleStencil
    }
    },

It's options API as you desire and it makes perfect sense, because in your case the stencil component is the computed property.

There is the example of the last approach.

MarisKay commented 2 years ago

Thank you so much, makes perfect sense! This is my 2nd month of Vueing, so lots to learn still! :)

Norserium commented 2 years ago

@MarisKay, you are welcome!

Alas, the passing components as a props is not common thing in the Vue world. I spent much time to find the reasonable alternative when I started to develop this library, and I didn't found it. The slots were close, but not enough.

Although, the using of Composable API or JSX makes the passing components much easier, so I assume this behavior will be stay same in the future versions. Furthermore, there are plans to give developers the possibility to change components for other cropper parts (not only the stencil).

Summing up, it's okay, that it was the trouble for you. But I'm not sure that I can change something here. I only hope that people who encounter the similar troubles in the future will find the answer here too.