Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
peterfoers opened this issue Jan 5, 2024 · 6 comments
Open

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

peterfoers opened this issue Jan 5, 2024 · 6 comments

Comments

@peterfoers
Copy link

peterfoers commented Jan 5, 2024

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.

@Norserium
Copy link
Collaborator

@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
Copy link
Collaborator

@peterfoers, any news?

@unpseudocomplique
Copy link

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 ?

@Norserium
Copy link
Collaborator

@unpseudocomplique, what's error did you get?

@christianbeecham
Copy link

christianbeecham commented Aug 9, 2024

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

@Asanalii
Copy link

Asanalii commented Oct 31, 2024

Hi there!
I have the same issue
image

this is my change

const onChangeCropper = ({ coordinates, canvas }) => {
console.log(canvas);
console.log(coordinates);
uploadedPhoto.value.second = canvas.toDataUrl();
};

this is my cropper
`

    <cropper
          ref="cropperRef"
          :src="uploadedPhoto.second"
          class="cropper"
          image-restriction="stencil"
          :canvas="true"
          :resize-image="{
            adjustStencil: false,
          }"
          :stencil-props="{
            handlers: {
              eastNorth: true,
              westNorth: true,
              westSouth: true,
              eastSouth: true,
            },
            movable: false,
            resizable: false,
            aspectRatio: 1.3333,
            lines: {},
          }"
          :stencil-size="{
            width: 100,
          }"
          @change="onChangeCropper"
        />

`
I m using Composition API <script setup>, can someone help?

christianbeecham In previews answer said that adding :canvas="true" helped, but in my situation is not working, so thanks in advance!

EDIT:
I found this solution for this
`
const onChangeCropper = () => {
const canvas = cropperRef.value.getCanvas();
const check = uploadedPhoto.value.first;

canvas.toBlob((blob) => {
croppedPhoto.value = { first: check, second: blob };
});
};
`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants