Skip to content

Help Migrating from Cropperjs v1 to v2 #1240

@leknoppix

Description

@leknoppix

Description

I'm trying to migrate my existing image cropping functionality from Cropperjs v1 to v2. I have a working script with v1 that allows users to crop images with a fixed aspect ratio, preview the result, and save the cropped image. However, I'm encountering issues when adapting this script to work with v2.

Current Working Script (v1)

Here's my current working script using Cropperjs v1:

import Cropper from 'cropperjs';

document.addEventListener('DOMContentLoaded', function () {
    let boutonsave = document.querySelector('#buttonsave') !== null;
    if (boutonsave) {
        document.querySelector('#buttonsave').style.visibility = "hidden";
        var image = document.querySelector('#imagearedimentionner');
        var buttonapercu = document.getElementById('buttonapercu');
        var buttonsave = document.getElementById('buttonsave');
        var result = document.getElementById('resultat');
        var dimensions = image.dataset.dimension;
        var tableau = image.dataset.tableau;
        var namefile = image.dataset.namefile;
        var original = image.dataset.original;
        var type = image.dataset.type;
        var dimension = dimensions.split('X');
        var AspectRatioRecadrage = dimension[0] / dimension[1];
        var cropper = new Cropper(image, {
            ready: function (event) {
                var cropper = this.cropper;
                var containerData = cropper.getContainerData();
                var cropBoxData = cropper.getCropBoxData();
                var aspectRatio = cropBoxData.width / cropBoxData.height;
                var newCropBoxWidth;
                if (aspectRatio < AspectRatioRecadrage || aspectRatio > AspectRatioRecadrage) {
                    newCropBoxWidth = cropBoxData.height * ((AspectRatioRecadrage + AspectRatioRecadrage) / 2);
                    cropper.setCropBoxData({
                        left: (containerData.width - newCropBoxWidth) / 2,
                        width: newCropBoxWidth
                    });
                }
            },
            cropmove: function (event) {
                var cropper = this.cropper;
                var cropBoxData = cropper.getCropBoxData();
                var aspectRatio = cropBoxData.width / cropBoxData.height;
                if (aspectRatio < AspectRatioRecadrage) {
                    cropper.setCropBoxData({
                        width: cropBoxData.height * AspectRatioRecadrage
                    });
                } else if (aspectRatio > AspectRatioRecadrage) {
                    cropper.setCropBoxData({
                        width: cropBoxData.height * AspectRatioRecadrage
                    });
                } else if (aspectRatio == AspectRatioRecadrage) {
                    cropper.setCropBoxData({
                        width: cropBoxData.height * AspectRatioRecadrage
                    });
                }
            }
        });
        buttonapercu.addEventListener('click', function (event) {
            event.preventDefault();
            result.innerHTML = '';
            result.appendChild(cropper.getCroppedCanvas());
            document.querySelector('#buttonsave').style.visibility = "visible";
        });
        buttonsave.addEventListener('click', function (event) {
            event.preventDefault();
            var crop = cropper.getCroppedCanvas({
                fillColor: '#fff'
            });
            result.innerHTML = '';
            result.appendChild(crop);
            const file = crop.toDataURL(type);
            var formData = new FormData();
            formData.append("croppedImage", file);
            formData.append("namefile", namefile);
            formData.append("tableau", tableau);
            formData.append("original", original);
            let response = fetch(document.location.pathname, {
                method: 'POST',
                headers: {
                    'X-Requested-With': 'XMLHttpRequest',
                    'X-CSRF-TOKEN': document.head.querySelector('[name=csrf-token]').content,
                },
                body: formData
            }).then(response => {
                alert('L\'image a été recadré');
                window.location.href = document.body.querySelector('#redirect>a').href;
            });
        });
    }
});

Issues with v2 Migration
When trying to adapt this script to v2, I'm encountering the following error:

Uncaught TypeError: d.getCroppedCanvas is not a function

I've tried several approaches:

  1. Using the Web Components approach with , , and elements
  2. Using the $toCanvas() method instead of getCroppedCanvas()
  3. Different ways of initializing the cropper

"Here's my attempt at adapting the script to v2. The image appears very small, and I can't properly crop it. Any guidance on what I'm doing wrong would be greatly appreciated."

// Import de cropperjs v2
import 'cropperjs';

document.addEventListener('DOMContentLoaded', function () {
    let boutonsave = document.querySelector('#buttonsave') !== null;
    if (boutonsave) {
        document.querySelector('#buttonsave').style.visibility = "hidden";
        var image = document.querySelector('#imagearedimentionner');
        var buttonapercu = document.getElementById('buttonapercu');
        var buttonsave = document.getElementById('buttonsave');
        var result = document.getElementById('resultat');
        var dimensions = image.dataset.dimension;
        var tableau = image.dataset.tableau;
        var namefile = image.dataset.namefile;
        var original = image.dataset.original;
        var type = image.dataset.type;
        var dimension = dimensions.split('X');
        var AspectRatioRecadrage = dimension[0] / dimension[1];

        // Créer le conteneur pour le cropper
        const container = document.createElement('div');
        container.style.maxWidth = '100%';
        
        // Créer les éléments du cropper v2
        container.innerHTML = `
            <cropper-canvas style="width: 100%;">
                <cropper-image src="${image.src}" style="max-width: 100%;"></cropper-image>
                <cropper-selection aspect-ratio="${AspectRatioRecadrage}" style="width: 80%; height: 80%;"></cropper-selection>
                <cropper-handle action="move"></cropper-handle>
                <cropper-handle action="n"></cropper-handle>
                <cropper-handle action="e"></cropper-handle>
                <cropper-handle action="s"></cropper-handle>
                <cropper-handle action="w"></cropper-handle>
                <cropper-handle action="ne"></cropper-handle>
                <cropper-handle action="nw"></cropper-handle>
                <cropper-handle action="se"></cropper-handle>
                <cropper-handle action="sw"></cropper-handle>
                <cropper-grid></cropper-grid>
                <cropper-shade></cropper-shade>
            </cropper-canvas>
        `;
        
        // Remplacer l'image par le conteneur du cropper
        image.parentNode.replaceChild(container, image);
        
        // Attendre que les éléments personnalisés soient définis
        requestAnimationFrame(() => {
            const cropperSelection = container.querySelector('cropper-selection');
            
            // Gestion de l'aperçu
            buttonapercu.addEventListener('click', function (event) {
                event.preventDefault();
                result.innerHTML = '';
                
                // Utiliser la méthode $toCanvas pour obtenir le canvas recadré
                cropperSelection.$toCanvas({
                    fillColor: '#fff'
                }).then(canvas => {
                    result.appendChild(canvas);
                    document.querySelector('#buttonsave').style.visibility = "visible";
                }).catch(error => {
                    console.error("Erreur lors de la génération de l'aperçu:", error);
                });
            });
            
            // Gestion de la sauvegarde
            buttonsave.addEventListener('click', function (event) {
                event.preventDefault();
                
                // Utiliser la méthode $toCanvas pour obtenir le canvas recadré
                cropperSelection.$toCanvas({
                    fillColor: '#fff'
                }).then(crop => {
                    result.innerHTML = '';
                    result.appendChild(crop);
                    
                    // Conversion en données URL
                    const file = crop.toDataURL(type);
                    
                    // Préparation des données à envoyer
                    var formData = new FormData();
                    formData.append("croppedImage", file);
                    formData.append("namefile", namefile);
                    formData.append("tableau", tableau);
                    formData.append("original", original);
                    
                    // Envoi des données au serveur
                    fetch(document.location.pathname, {
                        method: 'POST',
                        headers: {
                            'X-Requested-With': 'XMLHttpRequest',
                            'X-CSRF-TOKEN': document.head.querySelector('[name=csrf-token]').content,
                        },
                        body: formData
                    }).then(response => {
                        alert('L\'image a été recadrée');
                        window.location.href = document.body.querySelector('#redirect>a').href;
                    }).catch(error => {
                        console.error('Erreur lors de la sauvegarde:', error);
                        alert('Une erreur est survenue lors de la sauvegarde de l\'image');
                    });
                }).catch(error => {
                    console.error("Erreur lors de la génération de l'image recadrée:", error);
                    alert('Une erreur est survenue lors de la génération de l\'image recadrée');
                });
            });
        });
    }
});

However, I'm still having issues with:

  • The image appearing too small in the cropper
  • The cropping functionality not working properly
  • Error when trying to generate the cropped canvas

What I Need Help With

  1. A clear example of how to migrate this specific script from v1 to v2
  2. Explanation of the key differences in API between versions that affect my use case
  3. Proper way to handle the cropped canvas generation in v2

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions