Parallax effect animation with TweenMax (part 2)

This is the second part (and most recent) of a parallax tutorial and animation using GSAP TweenMax. Before we begin a little bit of theory behind the parallax effect.

Parallax is a displacement or difference in the apparent position of an object viewed along two different lines of sight, and is measured by the angle or semi-angle of inclination between those two lines. The term is derived from the Greek παράλλαξις (parallaxis), meaning “alteration”. Nearby objects have a larger parallax than more distant objects when observed from different positions, so parallax can be used to determine distances.

Here’s an example of the final effect

See the Pen Parallax with Tweenmax by Michael Dobekidis (@netgfx) on CodePen.


The Markup

<div id="sky"></div>
<div id="ground-container">
  <div id="ground1"></div>
  <div id="ground2"></div>
  <div id="ground3"></div>
</div>
<div id="trees"></div>
<div id="leafsBG"></div>
<div class="raven sprite" id="raven"></div>

So we create one layer for each item that we want to animate


The Style

#sky {
  background: #000000;
  /* Old browsers */
 
  background: -moz-linear-gradient(left, #000000 0%, #ebf4cb 92%, #f9f9f2 100%);
  /* FF3.6+ */
 
  background: -webkit-gradient(linear, left top, right top, color-stop(0%, #000000), color-stop(92%, #ebf4cb), color-stop(100%, #f9f9f2));
  /* Chrome,Safari4+ */
 
  background: -webkit-linear-gradient(left, #000000 0%, #ebf4cb 92%, #f9f9f2 100%);
  /* Chrome10+,Safari5.1+ */
 
  background: -o-linear-gradient(left, #000000 0%, #ebf4cb 92%, #f9f9f2 100%);
  /* Opera 11.10+ */
 
  background: -ms-linear-gradient(left, #000000 0%, #ebf4cb 92%, #f9f9f2 100%);
  /* IE10+ */
 
  background: linear-gradient(to right, #000000 0%, #ebf4cb 92%, #f9f9f2 100%);
  /* W3C */
 
  filter: progid: DXImageTransform.Microsoft.gradient( startColorstr='#000000', endColorstr='#f9f9f2', GradientType=1);
  /* IE6-9 */
 
  width: 100%;
  height: 100%;
  display: block;
  position: fixed;
}

#ground1{
  width: 1024px;
  height: 351px;
  background: url("http://i221.photobucket.com/albums/dd22/djmid71/Ground_zpsy2gxhrsx.png");
  position: absolute;
  bottom: 0;
  left: 0;
  background-repeat: no-repeat;
}

#ground2{
  width: 1024px;
  height: 351px;
  background: url("http://i221.photobucket.com/albums/dd22/djmid71/Ground_zpsy2gxhrsx.png");
  position: absolute;
  bottom: 0;
  left: 1024px;
  background-repeat: no-repeat;
}

#ground3{
  width: 1024px;
  height: 351px;
  background: url("http://i221.photobucket.com/albums/dd22/djmid71/Ground_zpsy2gxhrsx.png");
  position: absolute;
  bottom: 0;
  left: 2048px;
  background-repeat: no-repeat;
}

#ground-container {
  position: absolute;
  width: 3072px;
  height: 351px;
  bottom: -165px;
  left:0;
  z-index: 8;
}

#leafsBG {
  width: 3840px;
  height: 952px;
  position: absolute;
  background: url("http://i221.photobucket.com/albums/dd22/djmid71/leafsBG_zpsrkvglqqu.png");
  background-repeat: repeat-x;
  left: 0;
  bottom: -260px;
  z-index: 2;
}

#bushes {
  width: 3840px;
  height: 292px;
  position: absolute;
  background: url("http://i221.photobucket.com/albums/dd22/djmid71/Lightened-Bushes_zpsywewqv3b.png");
  z-index: 5;
  left:0;
  bottom: 50px;
  background-repeat: repeat-x;
}

#trees {
  width: 4096px;
  background: url("http://i221.photobucket.com/albums/dd22/djmid71/trees_zps2wwdqnoh.png");
  background-repeat: repeat-x;
  position: absolute;
  height: 998px;
  bottom: -320px;
  z-index: 10;
}


/* raven */
.sprite {display:block; overflow:hidden; background-repeat: no-repeat;background-image:url("http://www.netgfx.com/trunk/games/raven.png");
position: absolute !important;z-index:100;width:205px; height:205px;bottom:100px !important;top: 50% !important;left: 100px !important;
}

The Sky was made with gradient style and no image was used. For the other items we set them as background-images and we repeat them 2 or 3 times, that way when the first part is off-screen we reset the position of the element and the movement seems smooth. You might notice that the width of the components is also 2 or 3 times as much as the initial image.
All elements are positioned as absolute so we can move them freely without constrains.


The Script

The most important part is to figure out the timings of the movements, so we divide each element by 3 based on its position (items closer to us appear to be moving faster) so each item that is further from the viewport has its animation speed divided by 3 more than the previous item.

So with that in mind we have the animations for the ground (closer to the viewport), trees, background-leafs(most further from the viewport)

TweenMax.to($("#ground-container"), 3, {repeat:-1,left:-1024, ease: Linear.easeNone, onUpdate: function(){
  meter.tick(); // time is in seconds
}});
TweenMax.to($("#trees"), 900, {repeat:-1,backgroundPositionX:-2048, ease:Linear.easeNone});
TweenMax.to($("#leafsBG"), 2700, {repeat:-1,backgroundPositionX:-1920, ease:Linear.easeNone});

You might notice that the ground animation has a timing of 3 seconds while the other two animations have 900 and 2700 timings and it appears wrong. This is not the case as the 900 is actually in miliseconds so that is 0.9 seconds and the leafs animation is done in 2.7 seconds. This is done because of the different sizes between the items.

For the raven animation I used a script called TweenSprite. I exported my spritesheet with TexturePacker and then passed the position values in an array.

You can find TweenSprite here: https://github.com/spalt08/TweenSprite/tree/master
And TexturePacker here: https://www.codeandweb.com/texturepacker

// raven animation

var values = [
  ["2px", "2px", "205px", "205px"],
  ["2px","209px", "205px", "205px"],
  ["2px", "416px", "205px", "205px"],
  ["209px", "209px", "205px", "205px"],
  ["209px", "416px", "205px", "205px"],
  ["416px", "2px", "205px", "205px"],
  ["416px", "209px", "205px", "205px"],
  ["416px", "416px", "205px", "205px"],
  ["623px", "2px", "205px", "205px"],
  ["623px", "209px", "205px", "205px"],
  ["623px", "416px", "205px", "205px"],
  ["830px", "2px", "205px", "205px"],
  ["830px", "209px", "205px", "205px"],
  ["830px", "416px", "205px", "205px"],
  ["1037px", "2px", "205px", "205px"],
  ["1037px", "209px", "205px", "205px"],
  ["1037px", "416px", "205px", "205px"],
  ["1244px", "2px", "205px", "205px"],
  ["1244px", "209px", "205px", "205px"],
  ["1244px", "416px", "205px", "205px"],
  ["1451px", "2px", "205px", "205px"],
  ["1658px", "2px", "205px", "205px"],
  ["1451px", "209px", "205px", "205px"],
  ["1451px", "416px", "205px", "205px"]
];

TweenMax.spriteSheet( document.getElementById("raven"), { original: ["205px", "205px"], data: values}, 1, { delay: 0, repeat: -1 });

And with this the parallax effect is complete, I hope you liked the tutorial. Let me know in the comments below!

Enjoy!

Tagged , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *