Recortando imágenes con JCrop y HTML 5 Canvas

Hace unas semanas estuve comentando la posibilidad de cargar una imagen al servidor desde un canvas de HTML 5. Normalmente, si queremos realizar esta operación es porque queremos modificar la misma antes de que sea subida.
En este post voy a contaros cómo recortar imágenes con el plugin JCrop y con la ayuda de canvas visualizar el resultado antes de enviarlo.

JCrop

JCrop se trata de un plugin que nos aporta la funcionalidad de recorte sobre una imagen. En los ejemplos que se muestran en la web utilizan las coordenadas ofrecidas por este plugin para enviarlas al servidor y que sea este el que realice el recorte. En este ejemplo, nos apoyamos en canvas para que la imagen ya pueda subir recortada:

<!DOCTYPE html>
<html>
<head>
    <title>JCrop + Canvas</title>
    <link href="Content/jquery.Jcrop.css" rel="stylesheet" />
</head>
    <body>
        <img alt="Unix" id="UnixImg" src="Content/unix.jpg" />
        <canvas id="canvasJCrop"></canvas>
        <span id="measures"></span>
        <canvas id="resizeCanvas"></canvas>
        <script src="Scripts/jquery-2.0.3.min.js"></script>
        <script src="Scripts/jquery.Jcrop.js"></script>
        <script src="Scripts/App/demo.js"></script>
    </body>
</html>

En la parte HTML estamos mostrando la imagen que queremos recortar, un canvas donde se verá el resultado y un segundo donde podemos visualizar una segunda imagen redimensionada, en el caso de que fuera necesario.

$(function () {

    function id(elem) {
        return document.getElementById(elem);
    }

    var canvas = id('canvasJCrop'),
        img = id('UnixImg'),
        measures = id('measures');

    function paintOnCanvas(coords) {
        console.log(coords);

        var context = canvas.getContext('2d');

        canvas.width = coords.w;
        canvas.height = coords.h;

        console.log([img, coords.x, coords.y, coords.w, coords.h, 0, 0, coords.w, coords.y]);
        context.drawImage(img, coords.x, coords.y, coords.w, coords.h, 0, 0, coords.w, coords.h);

        measures.innerText = "width: " + canvas.width + " height: " + canvas.height;

        if (canvas.height > 82 || canvas.width > 300) {

            var imgToResize = new Image();

            imgToResize.onload = function () {

                var maxWidth = 300, maxHeight = 82;

                //Image size
                var width = imgToResize.width,
                    height = imgToResize.height;

                //Resizing...
                if (width > maxWidth) {
                    height *= maxWidth / width;
                    width = maxWidth;
                }

                if (height > maxHeight) {
                    width *= maxHeight / height;
                    height = maxHeight;
                }

                var resizeCanvas = id('resizeCanvas');
                resizeCanvas.width = width;
                resizeCanvas.height = height;

                var ctx = resizeCanvas.getContext('2d');

                ctx.drawImage(imgToResize, 0, 0, width, height);

                measures.innerText = "width: " + canvas.width + " height: " + canvas.height;

            };

            imgToResize.src = canvas.toDataURL();
        }
    }

    $("#UnixImg").Jcrop({
        onSelect: paintOnCanvas,
        aspectRatio: null
    });
});

En la parte de JavaScript lo primero que hacemos es implementar la función que pintará y redimensionará la imagen, en el caso de que la misma tenga un alto o un ancho mayor que el establecido por nosotros, en este ejemplo el alto máximo son 82px y el ancho 300px.
Esta función se llamará cada vez que se haga una selección sobre el elemento y, durante en esa llamada, nuestra función recibirá las coordenadas necesarias para que el canvas pueda posicionarse en la original a través de drawImage.

Espero que haya sido de utilidad 🙂

¡Saludos!