简体   繁体   中英

canvas rotate isn't working as expected

http://jsfiddle.net/s1n6cssa/12/

HTML

<a href="#" id="rotate">Rotate</a>
<div id="print-region">
    <img class="overlay" src="http://www.itasveer.com/common/images/mobilecover/apple-5_5s.png" /> <span id="uploaded-image-container"></span>

    <img class="overlay" src="http://www.itasveer.com/common/images/mobilecover/apple-5_5s_white.png" />
</div>

CSS

#myCanvas {
height: 100%;
width: 100%;
background-color: blue;
}
#print-region {
    height: 542px;
    width: 520px;
    margin: 0;
    position: relative;
    overflow: hidden;
}
.overlay {
    position: absolute;
    pointer-events: none;
}
#rotate {
    width: 100px;
    height: 30px;
}

JAVASCRIPT

var context;
var canvas;
var nHeight;  //the new height after resizing
var nWidth;   //the new width after resizing
var TO_RADIANS = Math.PI / 180;
var imageObj = new Image();

//USE ONLY ONE OF THE BELOW IMAGES AT A TIME

//square image which does not distort after rotation
imageObj.src = "http://i.stack.imgur.com/hwxO6.png";


//rectangular image which distorts after rotation
<!-- imageObj.src = "http://g-ecx.images-amazon.com/images/G/01/electronics/detail-page/Klipsch-Image-S4-II-Black-Lifestyle.jpg"; -->


var originalWidth = imageObj.width;
var originalHeight = imageObj.height;

$('#myCanvas').remove();


//used by context.rotate and updated after every rotation
$("#uploaded-image-container").attr({
    rotation: 0
});

$("#uploaded-image-container").append("<canvas id='myCanvas'></canvas>");


$("#uploaded-image-container").css({
    "position": "absolute",
        "height": originalHeight / 3, //one-third size of the original height of the uploaded image
        "width": originalWidth / 3,
        "top": $('#print-region').height() / 3,
        "left": $('#print-region').width() / 3
});

canvas = document.getElementById('myCanvas');

context = canvas.getContext('2d');
nHeight = canvas.height = originalHeight / 3;
nWidth = canvas.width = originalWidth / 3;


imageObj.onload = function () {
    context.drawImage(imageObj, 0, 0, originalWidth / 3, originalHeight / 3);
};

$("#uploaded-image-container").draggable({
    snap: false,
    scroll: false,
    cursor: "move",
    containment: '#print-region'
});


$("#uploaded-image-container").resizable({
    handles: 'nw, ne, sw, se',
    aspectRatio: true,
    containment: '#print-region',

    resize: function (e, ui) {
        nHeight = ui.size.height;
        nWidth = ui.size.width;
    }
});


$("#rotate").click(function () {
    updateRotation($("#uploaded-image-container"));
});


var imageRotation = 0; // the angle that the image is rotated
var updateRotation = function (elem) {
    var angle = parseInt(elem.attr('rotation'));

//after rotation, the nWidth and nHeight are interchanged hence temp variables
    var tempHeight, tempWidth;

    if (angle == 0) {
        imageRotation = 90;
        elem.attr('rotation', 90);
        tempHeight = nWidth;
        tempWidth = nHeight;
    } else if (angle == 90) {
        imageRotation = 180;
        elem.attr('rotation', 180);
        tempHeight = nHeight;
        tempWidth = nWidth;
    } else if (angle == 180) {
        imageRotation = 270;
        elem.attr('rotation', 270);
        tempHeight = nWidth;
        tempWidth = nHeight;
    } else {
        imageRotation = 0;
        elem.attr('rotation', 0);
        tempHeight = nHeight;
        tempWidth = nWidth;
    }

    $("#uploaded-image-container").css({
        "height": tempHeight,
            "width": tempWidth
    });

    canvas.width = tempWidth;
    canvas.height = tempHeight;
    context.translate(tempWidth / 2, tempHeight / 2);
    context.rotate(imageRotation * TO_RADIANS);
    context.translate(-tempWidth / 2, -tempHeight / 2);
    context.drawImage(imageObj, 0, 0, tempWidth, tempHeight);
};

I wanted to take a snapshot of the part shown in the result of jsfiddle using html2canvas plugin. But html2canvas does not support CSS3 rotate property. So I used canvas to rotate image and the rotation is successfully captured by html2canvas.

In the above code, when I use a square image, it rotates perfectly but when a rectangular image is considered then the image width and height are distorted.

Any combination of resize, drag and rotate should not distort the image.

What is the issue?

Try this one http://jsfiddle.net/5hrx77nr/ fiddle.

context.drawImage(imageObj, 0, 0, 100, 100 * imageObj.height / imageObj.width)

By default html5 scale out image to canvas size, so you must manage image size manually.

you should explain a little bit more about what are you trying to do. I think rotation is not that complex

Anyway. I spotted an error on line 33, 34

nHeight = canvas.height = originalHeight / 3;
nWidth = canvas.width = originalWidth / 3;

Maybe what you meant is addition or multiplication?? Because a blue canvas appear and rotate after this is changed.

    nHeight = canvas.height + originalHeight / 3;
    nWidth = canvas.width + originalWidth / 3;

It's because you use temporary value(width and height) as orientation when drawing and scaling image. then orientation's value is applied to setContainerHeight and setContainerWidth; in short: you use same value as coordinates and scaling

I cannot see your first image(it is blocked in my country), maybe because it is square(width = height); thus no problem occur, but rectangular is width = 2 * height ; So use image ratio. This should work in any box shape

    var context;
    var canvas;
    var nHeight;
    var nWidth;
    var TO_RADIANS = Math.PI / 180;
    var imageObj = new Image();
     imageObj.src = "http://g-ecx.images-amazon.com/images/G/01/electronics/detail-page/Klipsch-Image-S4-II-Black-Lifestyle.jpg"; 


    var originalWidth = imageObj.width;
    var originalHeight = imageObj.height;

    $('#myCanvas').remove();
    $("#uploaded-image-container").attr({
        rotation: 0
    });

    $("#uploaded-image-container").append("<canvas id='myCanvas'></canvas>");


    $("#uploaded-image-container").css({
        "position": "absolute",
            "height": originalHeight / 3,
            "width": originalWidth / 3,
            "top": $('#print-region').height() / 3,
            "left": $('#print-region').width() / 3
    });

    canvas = document.getElementById('myCanvas');

    context = canvas.getContext('2d');
    nHeight = canvas.height ;
    nWidth = canvas.width ;


    imageObj.onload = function () {
        context.drawImage(imageObj, 0, 0, originalWidth / 3, originalHeight / 3);
    };

    $("#uploaded-image-container").draggable({
        snap: false,
        scroll: false,
        cursor: "move",
        containment: '#print-region'
    });


    $("#uploaded-image-container").resizable({
        handles: 'nw, ne, sw, se',
        aspectRatio: true,
        containment: '#print-region',

        resize: function (e, ui) {
            nHeight = ui.size.height;
            nWidth = ui.size.width;
        }
    });


    $("#rotate").click(function () {
        updateRotation($("#uploaded-image-container"));
    });

 var imageRotation = 0; // the angle that the image is rotated
var updateRotation = function (elem) {
    var angle = parseInt(elem.attr('rotation'));
    var ratio = nWidth/nHeight;
    var customX = nWidth, scaleX = nWidth;
    var customY = nHeight, scaleY = nHeight;
    var tempHeight, tempWidth;
    //the problem is in number 1 and 3 
    if (angle == 0) { //number 1
        imageRotation = 90;
        elem.attr('rotation', 90);
        tempHeight = nWidth;
        tempWidth = nHeight; customY = ratio*customY;
    } else if (angle == 90) { //number 2
        imageRotation = 180;
        elem.attr('rotation', 180);
        tempHeight = nHeight;
        tempWidth = nWidth ;
    } else if (angle == 180) {
        imageRotation = 270;
        elem.attr('rotation', 270);
        tempHeight = nWidth;
        tempWidth = nHeight;  customY = ratio*customY;
    } else { // number 4 handle 
        imageRotation = 0;
        elem.attr('rotation', 0);
        tempHeight = nHeight;
        tempWidth = nWidth;
    }

    $("#uploaded-image-container").css({
        "height": tempHeight,
        "width": tempWidth
    });

    canvas.width = customX;
    canvas.height = customY;
    context.translate(customX / 2, customY / 2);
    context.rotate(imageRotation * TO_RADIANS);
    context.translate( -customX / 2, -customY / 2);        
    context.drawImage(imageObj, 0, 0, customX, customY);
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM