I haven’t taken calculus in years and I haven’t needed it since college. But today I did. I needed to animate an object going in a circular motion over a graphic of a face in an iPhone/iOS app I’m developing. These examples are purely wire framed with no official graphics or design.
What You Need
- An AbsoluteLayout view
- An Image view (or whatever you’d like really) inside that AbsoluteLayout
- A starting x and y coordinate which will be the center of your circular path
- Radius of the circle you want for your path
- Angle (or animation speed)
We are going to build our layout dynamically. I found this to be the best method for sizing things and positioning our elements. Let’s take a look at that code.
First we need some xml to hold our generated layout items. A simple stack layout works here, I use the horizonalAlignment and verticalAlignment to fill up the screen. Well, it’s supposed to but doesn’t seem to function just right depending on the xml around it. Still, it will work well enough for our demo here.
<StackLayout id="main-layout" orientation="vertical"
Let’s fill that with some elements we want for our circular animation. I’ve loaded this example code up with comments to explain what’s happening but I’ll point some important bits after this code block.
So our angle variable in combination with our duration speed is what controls the speed of our animation. Each “frame” is 1000 milliseconds which is set at the very end of the setInterval function’s code block, the second parameter.
Our call to .animate() has duration: 1000 ms as well so the time it will take to transition to the next point on the circle is also 1 second. If you think about this that means it’s going to move in a straight line from one point on the circle to the next as in this graph below. Within 1 second, before the next frame’s location on the circle path is calculated, it animates the transition between points.
Imagine the little red circles are the calculated points transitioned to every 1 second of setInterval(). Our object moves in a straight line between them over the course of that one second.
The oddest problem I encountered was that my animated object shot to the outer radius of the circle from the center of it before starting reach the initial calculated frame. What was happening is that the object is animated to it’s next frame based on it’s original x and y position. So each calculation is based on that. Since I start at a 0 degree angle the y axis doesn’t change when it starts but the x axis does.
I tried changing the xOrigin property to 50 (the radius) less than where I plotted it in hopes this would allow all future transition calculations to be based on that and it would seamlessly animate from the beginning but that didn’t seem to work. So you can see in the code my solution is to subtract 50 from the x when calculated and it gives a calculation like the xOrigin is 50 less. This seems to work just fine.
In my project I have a start and stop button. It also has a timer countdown which is not complete yet so the code isn’t going to do anything when the timer runs out. You can see it in the main video above. I’ll post that full code below so maybe you can use some of the functionality. It’s not commented as cleanly but notice in the xml that there are start and stop buttons with “tap” parameter which calls the respective functions in our .js file.