How to animate objects on a website? There are several choices. One of the wiser ones is to use javascript.
A while ago I had the opportunity to work with Angry Creative on an exciting project – The Meat Bar. The site was designed by Lobby Design and it was our responsibility to programme the site. In addition to creating a website in WordPress and a “light version” of the site for mobile devices, we did something really awesome with the “regular” page that appears when you surf in with the computer. There are sausages, hams and other meats on the page and the client thought it would be nice if they could sway a little.
Animating an object in basic movements with javascript is not very difficult, especially if you are used to using css. It’s all about setting new values for how the objects are positioned. In css you might set a value for the distance between the left edge and the object like this:
#object {
left: 100px;
}
You do something similar when you set a new value with javascript:
document.getElementById('object').style.left = '100px';
Basically, it is quite easy to make an object move. For example, you can make a loop.
for (int i = 0; i
There are still some things to keep in mind.
You cannot use an object’s id before the object is created. Therefore, it might be a good idea to put an onload event in the body tag. Then you know that your object is created when you use it.
You want to be able to put a delay on the movement. If you were to use the for loop above, the object would quickly swish from point A to point B. In our case, we want a smooth, slow movement. I solved this by using global variables to keep track of the start and end points and letting a custom function do the animation. (Calculate new values for the object and set them.) The last thing that happens in the function is that it calls itself with a certain time delay.
function AnimateMeat () {
// Make a step of the animation.
// nTimeOut is a global variable, makes it easier to
// keep the settings in one place.
t = setTimeout("AnimateMeat()", nTimeOut);
}
In addition, we want to be able to let different objects oscillate at different speeds. We solve this by giving each object its own speed variable, like this.
fSpeed = 0.3;
Now you can’t set a position to a decimal number, but that’s easily fixed with rounding. Calculate a new value for the position and set the new value. Since fSpeed is less than 1 in this case, the object will not be moved at all in all cycles. Since the cycles are quite close anyway, it will not look choppy anyway. You have to experiment to find the values that work.
// fCurrentX is the variable we use to keep track of where the object should be placed in x-direction.
fCurrentX = fSpeed; // Increase the x-position with fSpeed.
document.getElementById('the object').style.left = Math.floor(fCurrentX) "px";
The object should change direction and the movement should be stationary. To make the motion oscillate, the object must change direction. It is not that difficult, the only thing to do is to set the speed to the negative speed. The next time you run the animation part, you will then add a negative number, i.e. subtract. And the beauty of the crow song is that it works just as well the other way round. When you set the speed to negative speed again, it will become positive again. We also want the speed to slow down, for the pendulum to eventually come to rest. Therefore, we take the opportunity to multiply the speed by an appropriate factor. We also want to move the end point slightly. Not only do we want the speed of the movement to slow down, but we also want it to not move quite as far next time.
if (fCurrentX > fEndX) {
fSpeed = -fSpeed * 0.95; // The speed is set to negative to reverse the movement.
fEndX -= Math.abs(fSpeed); // Moves the turning point slightly to the left until next time.
}
And correspondingly in the other direction, of course. Then I have also checked if the speed is too low or if it is too close between the start and end point. In that case the movement should stop. There will be so many small movements that can be perceived as choppy and unnatural otherwise.
if ((Math.abs(fEndX - fStartX)
How to make the object wait? We didn’t want new animations to start as soon as the old one had ended, so I set up a wait variable. If the wait variable is 0, the animation should continue, otherwise it should subtract a certain value from the wait variable and skip the current cycle.
if (nWait
How to make the objects start randomly so that the movement is not the same every time? Through the marvellous random method. Random returns a random number between 0 and 1.
nWait = (Math.floor(Math.random()*500) * 10) 2000;
First we multiply by 500 and get a number between 0 and 500. To remove the decimal part, we round the number and then add a zero. The random number will thus be somewhere between 0-5000 ms or 0-5 seconds. To avoid the risk of movements starting immediately, we add two seconds. The new movement will thus start after 2-7 seconds.
If left does not work. Some of the objects cannot be left because they are background images. (And the reason why they are background images is that they should not give scroll bars far to the right, but that’s another story.) Then you can set background-position. Instead of
document.getElementById('object').style.left = Math.floor(fCurrentX) "px";
you then write
document.getElementById('object').style.backgroundPosition = Math.floor(fCurrentX) "px top";
Otherwise the solutions are the same. Remember to print top (or whatever other parameter you have set the background image to).
How do you get the layout when the width is not fixed? For example, you can start from the centre. The centre is usually fixed, so even if the width changes, you can relate to it.
// Unfortunately, not all ways of checking the width of the window work the same in all browsers.
if (typeof window.innerWidth != 'undefined') {
nWidth = window.innerWidth;
} else if (typeof document.documentElement != 'undefined'
&& typeof document.documentElement.clientWidth != 'undefined'
&& document.documentElement.clientWidth != 0) {
// IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)
nWidth = document.documentElement.clientWidth;
} else {
// older versions of IE
nWidth = document.getElementsByTagName('body')[0].clientWidth;
}
nCentre = parseInt(nWidth / 2);
fCurrentX = nCentre - 395;
Also, keep in mind to load new values if the user resizes their browser window.
How do you keep track of all objects when you have several? I used a multidimensional array. Unfortunately, the array didn’t quite keep up when I tried to set different values directly, so I used local variables that I read in from the array, did all the calculations, and then wrote values back to the array.
var arrMeat = new Array("salami", "langa sausages", "sawwrap", "cone wrap");
for (var i = 0; i
What else could have been done? You could have worked on rotating the images, using a specific attachment point. Like holding a pendulum and seeing where the pendulum is attached. I also tried experimenting with changing the y-position of the images, but it didn’t turn out well, it didn’t look natural.
As usual, Internet Explorer made some extra demands. The most prominent one was that the commute seemed to hack in IE8 and earlier. I solved it by setting a different speed if the browser was earlier than IE9. This function was on stackoverflow.com:
var ie = (function(){
var undef,
v = 3,
div = document.createElement('div'),
all = div.getElementsByTagName('i');
while (
div.innerHTML = '
',
all[0]
);
return v > 4 ? v : undef;
}());
It lets me set a custom speed value for IE like this:
if (ie
Mikael is the founder of emmio.se. He has been working with web development since 1999 and enjoys getting fun technologies to do useful things.