Animating CSS elements on a virtual 3D wheel
If you are one of those people who remember everything from your high school trigonometry class, then you don’t need to read this, but for the rest of us who only remember that SIN and COSINE had something to do with circles and a thing called PI , then this should be helpful.For a recent project I had to create an animated rotator in Javascript that needed to seem like a large slot machine wheel that was rotating. After Googling the web, I found a lot of articles that showed all of the jQuery mechanics for rotating images and elements and a lot of sample code for image rotators, but they were always in a flat, 2D format. Fortunately I have been playing with 3D programming recently and realized that creating this illusion can be pretty easy and a bit fun (if you’re a nerd. The fact that my dad taught trigonometry helped a bit too!)
For the actual CSS elements, I simply created standard DIV elements that contained the text and images. The elements are positioned in a containing DIV with their position set to relative.
The first thing one might think to do is to simply increase the value of the TOP property and then do something to change the width as it moves. However, for a good 3D effect what I really wanted was for elements near the top and the bottom to slow down and overlap as if they were really on a 3 dimensional wheel and moving back away from the viewer as the wheel rotated. To accomplish that, the first step is to understand that the value that should be changed over time is not the TOP or Y position but the number of degrees that the virtual wheel has turned.
So at first you might ask, should we move 0 to 180 degrees? For the application here, we need to look at the native Javascript math library and see what kind of parameters it takes. And also to remember the “unit circle” from trig class. We will need to use the Math.Sin and Math.Cos functions. In Javascript as in many languages, they are based in radians and not degrees, therefore a circle goes from 0 to 2PI. Also, the circle can be expressed in terms of half the circle being 0 to PI and the other half being 0 to -PI as shown by the diagram on my whiteboard here:
Actual photo of whiteboard taken with iPhone
So our Javascript program loop then basically iterates from (Javascript) Math.PI / 2 to -Math.PI /2 incrementing by whatever you want for animation smoothness. The reason for this specific range is where the viewer will be (in our virtual 3D world). The viewer will be looking at the imaginary wheel from the direction of zero degrees. There are then 3 cases to consider: 1) the position at the top of the wheel. 2) the position in the middle and 3) the position at the bottom. If you are looking at the wheel from the side then the top is PI/2, the center is zero and the bottom is -PI/2 (see the whiteboard sketch). Thus in Javascript we get Math.PI /2 (top) to -Math.PI /2 (bottom).
Now we must code to position and size the elements. We must find out for each element 1) what should the TOP value be and 2) what is it’s WIDTH. When writing functions to handle situations like this, I generally like the functions to work in terms of percentages instead of actual TOP and WIDTH values, you can then multiply the percentages by whatever your UI is using for the actual values.
In trigonometry the magical SIN function takes the degree of an angle and tells you what the Y distance from the circle center will be and the COS function will return the X distance from the center of the wheel. (or Z distance if viewing the wheel from the side)
That’s really all the trigonometry math you need to know for many 3D applications.
So then the to get the TOP or Y position of an element we would use the code:
var VerticalPercent = Math.sin(angle);
This gives a decimal number that is normally 0 to 1, but since we are actually using positive and negative numbers, we will get 1 to -1 as shown in the diagram. The bottom of the wheel is -1 and 1 is at the top.
Then take the VerticalPercent variable from above and multiply it by the actual height of the container to get the value in pixels:
(pseudocode)
DivTop = VerticalPercent * {container height};
To get the width of the element, we cheat a bit. We are really trying to simulate what real elements might look like depending on how far back from the user they are. There are many complicated 3D calculations that can do this (used in 3D games), but for this application we just want a close approximation that is believable. So what we will do is simply shrink an element in proportion to how far away from the viewer it is.
First we need to know, in the virtual world how far back from the screen it should be, this is:
var HorizontalDistance = Math.cos(angle);
In looking at the diagram of the circle, when the point on the virtual wheel is vertically in line with the center of the wheel (at the top) then it’s COS value will be zero and when it is closest to the viewer it will be 1. (see whiteboard sketch, viewer would be to the right)
To give the illusion of depth I did 2 things with this distance value. I used it for the opacity of the element and I used it to size the height and width of the element.
(pseudocode)
Width = HorizontalDistance * {element width}
Height = HorizontalDistance * {element height}
Opacity = HorizontalDistance
That’s all there is to it. I found that using the SIN and COS functions to simulate a virtual wheel really made the 3D illusion believable, especially when you see it animating. This of course greatly enhances the user experience with the UI.






Keep posting stuff like this i really like it
My cousin recommended this blog and she was totally right keep up the fantastic work!
What a great resource!
Really nice and impressive blog i found today.