Max William Vitorino Max William Vitorino - 7 months ago 35
Javascript Question

Rotate + Zoom Image

I need three basic functions for manipulating an image:


  1. Rotate the image;

  2. Zoom the image;

  3. Move the image.



I'm now trying to zoom the picture, but it has to keep the rotated image, if I have rotated it.

And I need to move the image with the mouse while keeping the features of zoom and rotate if it is rotated.

jQuery('#zoom').click(function(){
element.clearRect(0, 0, canvas.width, canvas.height);
larguraNova = ( canvasWidth + (escalaPixel * valorZoom) );
if(larguraNova > canvasWidth){
/* passo a nova largura que é igual a altura */
novosDadosWH = larguraNova;
novosDadosTRBL = ( ( larguraNova - canvasWidth ) / 2 ) ;
} else {
/* passo o valor original */
novosDadosH = novosDadosW = canvasWidth;
}
});


Fiddle

K3N K3N
Answer

See here for some changes to allow zoom and keep rotation:

Modified fiddle

You don't need to use save/restore for this as you are constantly changing the zoom and rotation. Let them accumulate. Ok, I missed that you wanted to translate the canvas as well. In that case it will be complicated to accumulate so in that case DO use save and restore :)

However, you can refactor the code so that you do rotation and zooming in one place and moving in the mouse move event.

Move the translate to global (or as here, to your image load which normally is in global) so you have a center starting point.

The following modifications are made (see updated fiddle above):

// set delta for zoom and keep track of current zoom
var zoomDelta = 0.1;
var currentScale = 1;

// set delta for rotation and keep of current rotation
var currentAngle = 0;
var startX, startY, isDown = false;

Simplified load (I would recommend doing this on window.onload instead):

jQuery('#carregar').click(function () {
    element.translate(canvas.width / 2, canvas.height / 2);

    // the new refactored function common to all steps
    drawImage();

    jQuery('#canvas').attr('data-girar', 0);
    this.disabled = true;
});

The rotation functions are now reduced to:

jQuery('#giraresq').click(function () {
    angleInDegrees = 90;
    currentAngle += angleInDegrees;
    drawImage()
});

jQuery('#girardir').click(function () {
    angleInDegrees = -90;
    currentAngle += angleInDegrees;
    drawImage()
});

The zoom functions:

jQuery('#zoomIn').click(function () {
    currentScale += zoomDelta;
    drawImage()
});
jQuery('#zoomOut').click(function () {
    currentScale -= zoomDelta;
    drawImage();
});

To move the canvas we need to keep track of mouse down, up and move:

canvas.onmousedown = function (e) {
    var pos = getMousePos(canvas, e);
    startX = pos.x;  // store current position
    startY = pos.y;

    isDown = true;   // mark that we are in move operation
}

canvas.onmousemove = function (e) {
    if (isDown === true) {
        var pos = getMousePos(canvas, e);
        var x = pos.x;
        var y = pos.y;

        // translate difference from now and start
        element.translate(x - startX, y - startY);
        drawImage();

        // update start positions for next loop
        startX = x;
        startY = y;
    }
}

// reset move operation status
canvas.onmouseup = function (e) {
    isDown = false;
}

The refactored function now do all the clearing, rotation and zooming:

function drawImage() {
    clear();

    element.save(); // as we now keep track ourselves of angle/zoom due to
                    // translation, we can use save/restore

    element.scale(currentScale, currentScale);
    element.rotate(currentAngle * Math.PI / 180);
    element.drawImage(image, -image.width * 0.5, -image.width * 0.5);

    element.restore();
}