Corey Tegeler
Corey Tegeler

Reputation: 149

Image rotate based on mouse location

I have the below script set to rotate the circle in the center of my page to follow the movements of the cursor. It was originally created to follow the movement in a contained box but I'm trying to get it to follow the circle all around the page but I'm not sure how to go about that properly, any insight you could share?

   var circle = $('#circle');
   var offset = circle.offset();
    
        function mouse(e) {

            var center_x = (offset.left) + ( $('#home').width() / 2 );
            var center_y = (offset.top) + ( $('#home').height() / 2 );
            var mouse_x = e.pageX; 
            var mouse_y = e.pageY;

            var radians = Math.atan2(mouse_x - center_x, mouse_y - center_y);
            var degree = (radians * (180 / Math.PI) * -1) + 180; 
            
            circle.css('-moz-transform', 'rotate('+degree+'deg)');
            circle.css('-webkit-transform', 'rotate('+degree+'deg)');
            circle.css('-o-transform', 'rotate('+degree+'deg)');
            circle.css('-ms-transform', 'rotate('+degree+'deg)');
            
        }

Upvotes: 0

Views: 1591

Answers (1)

Marc Marta
Marc Marta

Reputation: 542

This should work:

var circle = $('#circle');
var circleCenterX = circle.width() / 2; //Calculate these once
var circleCenterY = circle.height() / 2;
var offset = circle.offset();

function mouse(e) {

    var center_x = (offset.left) + ( circleCenterX );
    var center_y = (offset.top) + ( circleCenterY );
    var mouse_x = e.pageX; 
    var mouse_y = e.pageY;

    var radians = Math.atan2(mouse_x - center_x, center_y - mouse_y); //y is backwards from cartesian coordinate system. No need to convert to degrees.

    circle.css('-moz-transform', 'rotate('+radians+'rad)');
    circle.css('-webkit-transform', 'rotate('+radians+'rad)');
    circle.css('-o-transform', 'rotate('+radians+'rad)');
    circle.css('-ms-transform', 'rotate('+radians+'rad)');

}

Or, if you want it with delay (with a little cleaner code):

var circle = $('#circle');
var circleCenterX = circle.width() / 2;
var circleCenterY = circle.height() / 2;
var offset = circle.offset();
var radiansSet = new Array(9);
var radiansIntervalID = undefined;
var radians;

function mouse(e) {

    var center_x = offset.left + circleCenterX;
    var center_y = offset.top + circleCenterY;
    var mouse_x = e.pageX; 
    var mouse_y = e.pageY;

    radians = Math.atan2(mouse_x - center_x, center_y - mouse_y);

    if(radiansIntervalID === undefined) { //If not running the timer & mouse moved, start it!
        radiansIntervalID = setInterval(adjusterInterval, 20);
    }
}

var adjusterInterval = function() { //Interval to help rotate with slight delay
    var i = 0, len = radiansSet.length;
    var lastRad = radians;
    var anyDifferent = false;

    while(i < len - 1) { //Move down list of last checked mouse positions & check to see if different in 9 iterations.
        if(!anyDifferent && radiansSet[i] != lastRad) {
            anyDifferent = true;
        }
        radiansSet[i] = radiansSet[i + 1];
        lastRad = radiansSet[i];
        i++;
    }

    radiansSet[len - 1] = radians; //Append to last in list

    if(radiansSet[0] !== undefined) { //Change the first in the list (8 iterations ago)
        circle.css('-moz-transform', 'rotate(' + radiansSet[0] + 'rad)');
        circle.css('-webkit-transform', 'rotate(' + radiansSet[0] + 'rad)');
        circle.css('-o-transform', 'rotate(' + radiansSet[0] + 'rad)');
        circle.css('-ms-transform', 'rotate(' + radiansSet[0] + 'rad)');
    }

    if(!anyDifferent) { //If not changed....
        clearInterval(radiansIntervalID); //Turn off timer to save CPU
        radiansIntervalID = undefined;
    }
};

Tested this in my dev and it worked fine for me. Note that you can make the animation smoother by reducing the interval length, and make the delay longer by increasing the length of the radiansSet array.

Upvotes: 1

Related Questions