If you want to get straight to a working demo showing animation around a pivot point, view the jQuery pendulum animation here
The key to rotating an object element around a pivot point, such as a basic pendulum, is to setup your object (DIV element, or multiple DIVS) within a container element. The container acts as the pivot object that we animate and the child element(s) are offset to the location of the pivot centre. In this example I’ve used a single image as the child object – the ball and string – and absolutely positioned the top part of the pendulum to the centre of the container DIV.
The HTML and CSS setup for pendulum setup are as follows:
#pendulum-child { width:105px; height:623px; background-image:url(pendulum.png); position:absolute; left:-41px; top:10px; } #pendulum-parent { width:22px; height:22px; background-image:url(pendulum-pivot.png); }
<div id="demo-container"> <div id="pendulum-parent"> <div id="pendulum-child"></div> </div> </div>
As you can see the layout is very simple; two divs for the pendulum object – one acting as the object itself and a container div acting as the pivot point.
Next we create the animation in jQuery and all we need are three jQuery files. jQuery (obviously), ‘jquery css transform’ which allows us to do basic CSS3 transforms including translate, rotate and scale and the ‘css transform animation’ which, as the name suggests, allows for these transformations to be animated:
Using the regular jQuery ‘animate’ command, combined with the ‘rotate’ property, we can animate and rotate a html element as follows:
$('#divname').animate({rotate: 20},2000, "swing");
Where “20” is the degrees to rotate the div by (positive or negative), “2000” is the time in milliseconds and “swing” is the easing mode. jQuery has two animation easing modes. Linear and Swing, with swing being the default. Swing easing – or “slow fast slow” – is ideal for pendulum motion. The pendulum starts moving slow at the start of its swing, is fastest halfway through and slows down towards the end of the swing.
The full jQuery code for the pendulum animation is below and only a few lines are required.
<script type="text/javascript"> (function($) { $(document).ready(function() { var rotation = 30; var swingtime = 1600; function init() { $('#pendulum-parent').animate({rotate: rotation}, 0, function () { $('#pendulum-parent').css("display", "block"); rotation *= -1; pendulumswing(); }); } function pendulumswing() { $('#pendulum-parent').animate({rotate: rotation},swingtime, "swing", function(){ rotation *= -1; pendulumswing(); }); } init(); }); })(jQuery); </script>
There’s two variables; ‘rotation’ which sets how high the pendulum should swing and ‘swingtime’ which is the length it takes to complete one swing. The init function sets the initial position of the pendulum by instantly rotating it to it’s start position (before displaying it) and the swing function which is called at the start of each swing, reversing the direction of the rotation as it does so.
Important to note that the rotation transformation is not compatible with Internet Explorer 8 and below or really old versions of Safari and FireFox. As these older browsers are declining in market share, I’m seeing more of these kinds of transformations being used. One of the best examples for pivot point animation is how Apple use CSS3 transformations on their iPhone page to create great transitions, which uses plenty of images rotating around pivot points. If you try this in IE 8 however, a standard slider appears instead.
Update: FireFox 16 handles JS transformations differently, so if your jQuery animated rotations are greatly exaggerated, you should try updating to the latest version of the plugin: https://github.com/zachstronaut/jquery-animate-css-rotate-scale
Update 2: A strange bug has sometimes been causing the pendulum to freeze occasionally mid-swing. This can be fixed by changing the ‘swningtime’ variable to an odd number – e.g. 1603 instead of 1600. Not 100% sure why this occurs but probably has something to do with the rotational calculations being set to zero between the positive and negative rotational swing.
Update 3: Added a ‘swings’ variable to get the pendulum to come to a rest after a certain number of swings.
Many thanks for this, but how might I invert the pendulum – that is move the pivot point to the bottom, so that we have an effect like flowers on stems swaying in the wind.
Thanks
Hi John,
The best way to invert the pendulum and change the pivot point would be to move the child DIV in relation to the pivot point parent. In the demo above, if you change the CSS for “top” for #pendulum-child to a negative value, such as -400px, that should do the trick. You may also need to move the parent container down.
Tom
just what I needed thanks
Nice work, keep going!
But i’ve a question, how can I make the time infinity?
I tried to set this more milliseconds;
$(‘#divname’).animate({rotate: 20},2000, “swing”);
Awesome… got it to work… just need to put in my own images now…
As they say, one can never have enough. I was wondering if i could have like multiple pivot points … one pivot point per child so it could llook like parallel pendulums (i hope that makes sense) but KUDOS !!
Thanks,
Amrita
this the best one.
but it suddenly stops swinging. in all browsers
probably it also needs jquery easing plugin. i used it and it worked for me
Hey Tom,
How would you stop the pendulum in the middle of its movement?
Thanks,
Dhruv
Hi Tom,
Dhruv again. Thanks for answering my question, but I realized I intended to ask something else. Would it be possible to stop the pendulum in the middle of its swing, at a certain radius?
For example:
In my code the person presses the spacebar, and the pendulum is supposed to stop exactly at the radius it was at the time he pressed it.
How would I do that?
Thanks,
Dhruv
Hi
Great work! Really what I needed.
Only one little thing I don’t know how to fix it. I would like the pendulum slows down and stops slowly automatically after appr. 5 swings.
Can you help me?
tnx a lot!
Esther
hi tom.
wants to control pendullum swing time on bahalf of user define value .please suggest me how i will do that .???
Hi Tom
I have another problem.I want to start the movement of pendulum from the pivote point,neither from left or right.
Please suggest me what should we do now.
This is awesome, Tom! Just what I’ve been looking for!
I’m initiating the animation on hover, which works well, except the animation seems to begin at the rotation degree. Like from the side? So it jumps on mouseover straight to ninety degrees. Is there any way to start the animation from the still state, instead? So that it begins swinging up, instead of down?
Thanks!
Hi, I modified this so that it’s a clickable interaction with 4 different ‘spokes’. Just wondering if you knew a way to modify the code so that it could go backwards to it’s starting position? That way if I click one, the others will go back.
Hi Tom,
Thanks for the great plugin, works great!
I was wondering if you can help – while navigating with my menu which also uses jquery for animation and going back to the animation (all same page) the animation gets fucked up and becomes jagged…you can try to reproduce it here:
http://192.241.187.47/test/
Thanks a lot,
Joey
Hi Brian thanks for the great plugin
I have few problems perhaps you could help…
http://192.241.187.47/test/
I have duplicated the plugin to work on 7 divs, its moving and all is good
but at the 1st few seconds there’s a jump in the motion, and also I couldnt make it loop infinite
help please
Joe
This was exactly what i was looking for, Thanks a lot. Great post.
I ended up using just CSS3 to get that pendulum effect. Visit my technology page and hover over the title.
http://www.ashishdesai.com/#/tech. You can achieve it using just CSS Transform and rotations.
Awesome effect! Instead of starting the swing on $(document).ready, is there anyway i can initialize it when I hover over the container, maintaining the correct # of swings, swingtime, etc once initialized?
Thank you!
Hi Tom, I finally got it working by changing the ‘display’ css of #pendulum-parent to ‘block.’
I have no idea why this would make a difference on a hovering div, as I made no further changes to init(), but it works.
Thank you!
Hi, Can I change the direction of swing? For eg, if i want to swing the pendulum starting from right and then left what changes I have to do? Now it starts swinging from left to right.
Is there a way to make it use mobile devices accelerometer instead of a preset swing?
Hey Tom,
Amazing work you’ve done here! I know it’s been a while since you posted this – however I was wondering if I could still get some assistance?
I want to make this function run only whenever the user scrolls the page. I have tried ‘$(window).scroll(function(‘ with mixed, less than desirable results. I normally have someone else doing JS for me so I’m more of a beginner – any help would greatly be appreciated!
Thanks ๐
Hi Tom,
is it possible to make on hover the pendulum swing faster?
Awesome effect! Instead of starting the swing on $(document).ready, is there anyway i can initialize it when I hover over the container, maintaining the correct # of swings, swingtime, etc once initialized?
Thank you!
This was exactly what I needed. Thank you!