2
votes

I have a page with an image on it. Clicking and holding the mouse button while dragging the cursor around rotates the image about its center. This is accomplished with the following bit of JavaScript (based off of this answer to a similar question):

$(function() {
    var target = $('#david-hasselhoff'),
        originX = target.offset().left + target.width() / 2,
        originY = target.offset().top + target.height() / 2,
        dragging = false;

    target.mousedown(function(e) {
        dragging = true;
    });

    $(document).mouseup(function() {
        dragging = false
    }).mousemove(function(e) {
        var mouseX, mouseY, radians, degrees;

        if (!dragging) {
            return;
        }

        mouseX = e.pageX;
        mouseY = e.pageY;
        radians = Math.atan2(mouseY - originY, mouseX - originX),
        degrees = radians * (180 / Math.PI);

        target.css('-webkit-transform', 'rotate(' + degrees + 'deg)');
        target.css('-ms-transform', 'rotate(' + degrees + 'deg)');
        target.css('transform', 'rotate(' + degrees + 'deg)');
    });
});

There are two problems with this:

1) If I rotate the image, let go of the mouse button, and rotate the image again, the rotation is reset. I would like to be able to rotate it a little bit, then click and drag to rotate it a little more.

2) If I click on the left side of the image and rotate it clockwise a few degrees, it immediately sets the rotation to 180 degrees (or more like -170 degrees). I would like to be able to rotate the image as far as I drag the cursor regardless of which side of the center of the image it started on.

I hope that makes sense. Here's the fiddle: http://jsfiddle.net/C5QA9/

1

1 Answers

2
votes

The code that calculates the rotation here is getting the angle between the vertical center of the image and the current position of the cursor. In order to have the image rotate smoothly when you click, you need to subtract this angle during rotation. Additionally you need to track where the rotation was left during the previous drag and add this angle to the current rotation:

$(function() {
    var target = $('#david-hasselhoff'),
        originX = target.offset().left + target.width() / 2,
        originY = target.offset().top + target.height() / 2,
        dragging = false,
        startingDegrees = 0,
        lastDegrees = 0,
        currentDegrees = 0;

    target.mousedown(function(e) {
        dragging = true;
        mouseX = e.pageX;
        mouseY = e.pageY;
        radians = Math.atan2(mouseY - originY, mouseX - originX),
        startingDegrees = radians * (180 / Math.PI);
    });

    $(document).mouseup(function() {
        lastDegrees = currentDegrees;
        dragging = false;
    }).mousemove(function(e) {
        var mouseX, mouseY, radians, degrees;

        if (!dragging) {
            return;
        }

        mouseX = e.pageX;
        mouseY = e.pageY;
        radians = Math.atan2(mouseY - originY, mouseX - originX),
        degrees = radians * (180 / Math.PI) - startingDegrees + lastDegrees;

        currentDegrees = degrees;

        target.css('-webkit-transform', 'rotate(' + degrees + 'deg)');
        target.css('-ms-transform', 'rotate(' + degrees + 'deg)');
        target.css('transform', 'rotate(' + degrees + 'deg)');
    });
});

Here's the fiddle: http://jsfiddle.net/C5QA9/1/