vue-advanced-cropper icon indicating copy to clipboard operation
vue-advanced-cropper copied to clipboard

issue: getting canvas in composition api with <script setup>

Open peterfoers opened this issue 1 year ago • 5 comments

I'm trying to get the result of my crop in my setup function. According to the docs, this is the way in options API const { coordinates, canvas, } = this.$refs.cropper.getResult();. The composition way of doing this is like so:

<script setup>
import { ref, onMounted } from 'vue';
import { Cropper } from 'vue-advanced-cropper'
import 'vue-advanced-cropper/dist/style.css'

const cropper = ref(null) // Does not work
const title = ref(null) // Works 

onMounted(() => {
    console.log(cropper.value)
    console.log(title.value)
})

const cropperImage = ref('https://images.unsplash.com/photo-1600984575359-310ae7b6bdf2?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=700&q=80')

</script>

<template>
    <h1 ref="title">Some Value</h1>
    <cropper
        ref="cropper" class="cropper" :src="cropperImage" 
        style="margin: auto;"
        :stencil-props="{
            aspectRatio: 1,
            movable: false,
            resizable: false,
            handlers: {},
        }"
        :resize-image="{
            adjustStencil: false,
        }"
        image-restriction="stencil"
        />
    <label for="image" value="Image" />
    <input type="file" name="image" ref="image" class="form-control" @change="setImage"/>
</template>

<style>
.cropper {
    height: 200px;
    width: 200px;
    background: #DDD;
}
</style>

For the Cropper I get many warnings: Component is missing template or render function, Invalid vnode type when creating vnode: null. Over and over again. And the Component doesn't render.

It works without the syntactic sugar:

<script>
import { ref, onMounted } from 'vue';
import { Cropper } from 'vue-advanced-cropper'
import 'vue-advanced-cropper/dist/style.css'

export default {
    components: {
        Cropper,
    },
    setup() {
        const cropper = ref(null)
        const title = ref(null)

        onMounted(() => {
            console.log(cropper.value)
            console.log(title.value)
        })

        const cropperImage = ref('https://images.unsplash.com/photo-1600984575359-310ae7b6bdf2?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=700&q=80')

        return {
            cropper,
            title,
            cropperImage,
        }
    },
}
</script>

Any help is greatly appreciated.

peterfoers avatar Jan 05 '24 01:01 peterfoers

@peterfoers , pie in the sky, but try to rename cropper to cropperRef:

const cropperRef = ref(null) // Should work

It looks, that it conflicts with the import of Cropper component.

Norserium avatar Jan 20 '24 14:01 Norserium

@peterfoers, any news?

Norserium avatar Jun 15 '24 09:06 Norserium

Hi @Norserium i have the same issue,

          <Cropper
            ref="cropperComponent"
            class="cropper"
            :src="newImageDataUrl"
            :debounce="false"
            :stencil-props="{
              aspectRatio,
            }"
            @change="onChange"
          />

with

const cropperComponent = ref<any>(null)

const retreiveCroppedImage = async () => {
  console.log('cropperComponent.value', cropperComponent.value) // this log the correct vue instance

  // Fail here because cropper is not defined
  const { caneva } = cropperComponent.value.cropper.getResult()
  emits('updated:image', caneva.toDataURL())
}

I logged cropperComponent.value and found out i can access cropperComponent.value.getResult() and then this work:

const retreiveCroppedImage = async () => {
  console.log('cropperComponent.value', cropperComponent.value)
  const { canvas } = cropperComponent.value.getResult()
  console.log('result', result)
  emits('updated:image', canvas.toDataURL())
}

Something with composition api / script setup ?

unpseudocomplique avatar Jul 28 '24 09:07 unpseudocomplique

@unpseudocomplique, what's error did you get?

Norserium avatar Aug 01 '24 11:08 Norserium

Same here, using the composition api. With the code below I get "Canvas is undefined or null"

const submit = () => {
  if (cropperRef.value && cropperRef.value.getResult) {
    const result = cropperRef.value.getResult();
    console.log(result)

    if (result && result.canvas) {
      const dataUrl = result.canvas.toDataURL('image/png');
      console.log(dataUrl);
    } else {
      console.error('Canvas is undefined or null.');
    }
  } else {
    console.error('Cropper reference or getResult method is not available.');
  }
};
<div class="px-6">
      <cropper
          ref="cropperRef"
          class="twitter-cropper"
          background-class="bg-white"
          foreground-class="bg-white"
          image-restriction="stencil"
          :stencil-size="stencilSize"
          :stencil-props="{
            lines: {},
            handlers: {},
            movable: false,
            scalable: false,
            aspectRatio: 1,
            previewClass: 'twitter-cropper__stencil',
          }"
          :stencil-component="CircleStencil"
          :transitions="false"
          :canvas="false"
          :debounce="false"
          :default-size="defaultSize"
          :min-width="150"
          :min-height="200"
          :src="img.src"
          @change="onChange"
      />
    </div>

The console.log(result) which is logging the result of cropperRef.value.getResult() returns an object, which doesn't include the canvas

{
    "image": {
        "src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAB4AAAAPACAYAAADU.....",
        "width": 1920,
        "height": 960,
        "transforms": {
            "rotate": 0,
            "flip": {
                "horizontal": false,
                "vertical": false
            },
            "translateX": -160,
            "translateY": -4,
            "scaleX": 0.31666666666666665,
            "scaleY": 0.31666666666666665
        }
    },
    "coordinates": {
        "width": 960,
        "height": 960,
        "left": 0,
        "top": 0
    },
    "visibleArea": {
        "width": 1970.5263157894738,
        "height": 985.2631578947369,
        "left": -505.2631578947369,
        "top": -12.631578947368421
    },
    "imageTransforms": {
        "rotate": 0,
        "flip": {
            "horizontal": false,
            "vertical": false
        }
    }
}

EDIT - I fixed it by setting :canvas="true" on the component

christianbeecham avatar Aug 09 '24 15:08 christianbeecham