• ## Status:

• How to diff two streams instead of files (in zsh on OS X): diff <(cat file1.ext) <(cat file2.ext) 2012-02-08

### Animating Circles with JavaScript

23:53 Mon 19 Feb 2007

Years back I wrote some online tutorials on how to animate circular movement in Lingo and JavaScript. While moving my older articles to this site, I realized that I could not in good conscience move this one without updating it. So, a tutorial on circular animation in JavaScript follows.

First, some basic math.

We want to move an element in a circle. The element is a point that moves around the edge of this circle. At any given time we will have the radius of the circle, its center, and the angle at which the point is. Call the radius r, the center x,y and the angle a. So, from the above diagram, what we want to be able to work out is x1,y1 for any given values of a, r and x,y. To work out x1,y1 we need to reinterpret the arc of the circle as a right-angle triangle: It should be evident that y1= yd. In a normal co-oridinate system it would be y + d, but almost all computer graphical systems have 0,0 at the top left corner, not the bottom left.

The sin of an angle = the opposite over the hypoteneuse, and cos = the adjacent over the hypoteneuse. Therefore:

```sin a = d / r
r sin a = d
d = r sin a
```

and so:

```y1 = y - (r sin a)
```

As for x1: Since x1 = xe:

```cos a = e / r
r cos a = e
e = r sin a
```

and so:

```x1 = x - (r cos a)
```

So now we can express x1,y1 in terms of the values that we set.

(In the original, I was dealing with Lingo, the Director scripting language. I will include this script at the end, but with no claims for its accuracy, as about eight years have passed since I wrote it and I have no idea whatsoever about how Lingo works these days.)

One of the gotchas when I first tried this was that JavaScript thinks in radians, not degrees. Radians = (Degrees * (pi/180)), or:

``````

var pi = Math.PI;
var radians = (degrees * (pi/180));

}
``````

We need an element to work on, but we can create one at run time using DOM methods, so we’ll leave that for the moment.

We need animation, or a looping function. For this we use `setInterval()`. `setInterval()` takes two arguments: the function to run, and the interval after which it should be run (repeatedly). Before getting to that, here is the skeleton of the functions we’ll create and what we’re using them for:

``````
var circleMove = {

Degrees: 0,
timeId: 0,

moveElement: function(element, newLocX, newLocY) {
//Does the actual shifting of the element; takes element and x and y coordinates.
},

calculateCoordinates: function(theCenterPointX, theCenterPointY) {
//sets the degree variable, and loops if it's greater than 360, then calculates the Rads by calling convertDegreesToRadians, and then x, and y
},

},

circleElement: function(element, theCenterPointX, theCenterPointY, delayTime) {
//gets the new coordinates from calculateCoordinates() and sends them to moveElement()
},

init: function(element, theCenterPointX, theCenterPointY, delayTime) {
//clears the setInterval, and then sets it again. Also, creates the element if it does not exist.
}

}
``````

We’re first going to initialize the whole thing.

``````
init: function(elementId, theCenterPointX, theCenterPointY, delayTime) {
//first, check to see if the element exists:
var theElement = null;
if (!document.getElementById(elementId)) {
//if not, create it and give it some properties
theElement = document.createElement("div");
theElement.id = elementId;
theElement.style.height = "1em";
theElement.style.width = "1em";
theElement.style.border = "1px solid red";
document.body.appendChild(theElement);
} else {
theElement = document.getElementById(elementId);
}
//removes the looping on the element if it's already been set:
clearInterval(circleMove.timeID);

//starts the repetition.
circleMove.timeID = setInterval( function() {
circleMove.circleElement(theElement, theCenterPointX, theCenterPointY, delayTime);
}, delayTime);

}
``````

Next up is circleElement, which is little more than a wrapper function:

``````
circleElement: function(element, theCenterPointX, theCenterPointY, delayTime) {
var newCoordinates = circleMove.calculateCoordinates(theCenterPointX, theCenterPointY);
circleMove.moveElement(element, newCoordinates, newCoordinates);
},
``````
``` ```

``````
calculateCoordinates: function(theCenterPointX, theCenterPointY) {
//if the degree variable is greater than 360, reset it
if (circleMove.Degrees > 360) {
circleMove.Degrees = 1;

}
//increment the degree variable, then get the radians, and then calculate the coordinates
circleMove.Degrees = circleMove.Degrees + 1;
//return the coordinates as a two-value array
return [newLocX, newLocY];

},
``````
``` ```

``````
moveElement: function(element, newLocX, newLocY) {
//sets the top and left of the element style, thus moving it to its new location.
element.style.position = "absolute";
element.style.top = newLocX + "px";
element.style.left = newLocY + "px";
},
``````
``` ```

Finally, how do we call "init()" properly? We add a function that adds the init call itself to an element (and uses John Resig's addEvent), and then have that fire when the window loads:

``````

initStart: function() {
function callInit() {
circleMove.init("theMovingElement", this., 300, 10);
}

},

addEvent: function( obj, type, fn ) {
//John Resig's function for adding event handlers to objects.
if ( obj.attachEvent ) {
obj['e'+type+fn] = fn;
obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
obj.attachEvent( 'on'+type, obj[type+fn] );
} else {
}
}

``````

Lastly, we need .

You can view it all together (the version used also uses a script to calculate the current scroll position, so you can see the function work when you press that button!).

Finally, in case anyone's interested, here is that Lingo script (use at your own risk!):

```global gTheCenterPointy, gTheCenterPointx, gDegrees, gRadius, gRads
on exitFrame
set gDegrees = gDegrees + 1
if gDegrees > 360 then set gDegrees = 1
set the locV of sprite 2 to newLocV
set the locH of sprite 2 to newLocH
go to the frame
end
```

### 3 Responses to “Animating Circles with JavaScript”

1. Kaustav Mukherjee Says:

This program is so very convoluted! I wrote this rather small script to effect the same animation:

(Assuming the beginning co-ordinates of the box to be 200px to the right and 250px from the top and radius of the circle to be 200px, i.e. centre is at 400px to the right and 250px from the top. If you want different figures, change the values accordingly, it is very easy.). The HTML and CSS is not given..
``` ```

``````\$(function() {
\$("div#hot").bind('click',function() {
\$("div#hot").unbind('click');
var phi=0;
var int= 2*(Math.PI)/1000;
function cool() {
phi= (phi>=2*(Math.PI))? 0:(phi+int);
var \$m= 400-200*Math.cos(phi);
var \$n= 250-200*Math.sin(phi);
\$("div#hot").animate({marginLeft: \$m+'px', marginTop: \$n+'px'},1,cool);
}
cool();
});
});
``````
``` ```