akinuri
akinuri

Reputation: 12027

Rotation around a specific point

I'm trying to rotate an element around another element. I've put this code together, and even though the code works fine, I have a little problem with the element's rotation. It's not very accurate. The blue dot leaves the orbit when at the bottom.

I've played with the code but couldn't fix it. You can check the fiddle example.

rotateObj function taken from Felix Eve's answer.

function markCircleCenter(circ, orig) {
    if (typeof circ == "string") {
        var elm = document.getElementById(circ);
    } else { var circle = circ; }
    if (typeof orig == "string") {
        var mark = document.getElementById(orig);
    } else { var elm = orig; }
    var width       = parseInt(window.getComputedStyle(elm).width, 10);
    var height      = parseInt(window.getComputedStyle(elm).height, 10);
    var top         = parseInt(window.getComputedStyle(elm).top, 10);
    var left        = parseInt(window.getComputedStyle(elm).left, 10);
    var markWidth   = parseInt(window.getComputedStyle(mark).width, 10);
    var markHeight  = parseInt(window.getComputedStyle(mark).height, 10);
    var circle = {
        circle: elm,
        x: width/2 + left,
        y: height/2 + top,
    };
    mark.style.position = "absolute";
    mark.style.top      = circle.y - markWidth/2 + "px";
    mark.style.left     = circle.x - markHeight/2 + "px";
    document.body.insertBefore(mark, elm.nextSibling);
    return circle;
}

function placeObjIntoOrbit(obj) {
    if (typeof obj == "string") {
        var obj = document.getElementById(obj);
    } else { var obj = obj; }
    var objPos = {
        obj: obj,
        x: origin.x,
        y: parseInt(window.getComputedStyle(origin.circle).top, 10) - parseInt(window.getComputedStyle(obj).width, 10) / 2,
    };
    obj.style.position  = "absolute";
    obj.style.top       = objPos.y  + "px";
    obj.style.left      = objPos.x  + "px";
    return objPos;
}

function rotateObj(pointX, pointY, originX, originY, angle) {
    var angle = angle * Math.PI / 180.0;
    return {
        x: Math.cos(angle) * (pointX-originX) - Math.sin(angle) * (pointY-originY) + originX,
        y: Math.sin(angle) * (pointX-originX) + Math.cos(angle) * (pointY-originY) + originY,
    };
}

var angle   = 0;
var origin  = markCircleCenter("circle", "origin");
var point   = placeObjIntoOrbit("point");

function spin() {
    if (angle >= 360) { angle = 0; }
    angle += 2;
    var newCoor = rotateObj(point.x, point.y, origin.x, origin.y, angle);
    point.obj.style.left = newCoor.x + "px";
    point.obj.style.top  = newCoor.y + "px";
}
setInterval("spin('point')", 1000/30);

Upvotes: 0

Views: 333

Answers (1)

Ted Hopp
Ted Hopp

Reputation: 234795

You are computing the center of the point but positioning it using its top-left point. You need to take the dimension of the point into account when you position it. Try changing the last two lines in function spin() to:

point.obj.style.left = (newCoor.x - 4) + "px";
point.obj.style.top  = (newCoor.y - 4) + "px";

(You should get rid of the "- 4" and substitute half the width and height of the point, but this gets the idea across more tersely.)

Upvotes: 1

Related Questions