Animating the Cloud Modules Icon

Every time we launch a new product, we try to offer our users a delightful experience on our landing pages. This sometimes involves creating a nice animation that gives life to the product icon. We received so much great feedback for our Cloud Code icon animation that we really wanted to do something cool for our new Cloud Modules feature.

Today I’m giving you some insight on how we built the Cloud Modules icon animation, using JavaScript and a little bit of CSS3.

Let’s start by creating the HTML for this animation.

<div class="icon">
  <div class="bricks"></div>
  <div class="final_icon"></div>
</div>

We only need a div that will contain our little “bricks”, a div that will contain the final icon that will fade in at the end of the animation, and a wrapper div to correctly position the icon in the page.

Then we need to write the CSS that will make things look good.

.icon {
    position: relative;
    width: 435px;
    height: 284px;

    .bricks {
        .brick {
            width: 11px;
            height: 11px;
            @include border-radius(3px);
            @include background-image(linear-gradient(#FFFFFF, #B9B9B9));
            @include box-shadow(rgba(#FFFFFF, 0.7) 0px 0px 1px, rgba(#000000, 0.6) 0 2px 3px);
            position: absolute;
            @include single-transition(all, 0.5s, ease);

            &.displayNone {
                display: none;
            }

            &.illuminated {
              -webkit-animation: illuminatedBrick 0.7s ease-out 1;
              -moz-animation: illuminatedBrick 0.7s ease-out 1;
              animation: illuminatedBrick 0.7s ease-out 1;
            }
        }
    }
    .final_icon {
        display: none;
        margin-top: -17px;
        margin-left: -20px;
        width: 467px;
        height: 318px;
        position: absolute;
        background: url(/images/products/cloud_code/cloud_modules_final_icon.png) no-repeat;
        @include image-2x("/images/products/cloud_code/cloud_modules_final_icon@2x.png", 462px, 318px);
    }
}

Here we’re using some SASS mixins provided by Compass and a custom mixin for providing Retina assets from Jason Zimdars’s solution, and we’re also using a CSS animation called illuminatedBrick that we first need to declare.

@keyframes illuminatedBrick {
    0% {
        background-image: none;
        background-color: white;
        @include box-shadow(rgba(white, 0.7) 0px 0px 1px, rgba(#da79f3, 0.6) 0 0px 3px);
    }
    100% {
        background-image: none;
        background-color: #da79f3;
        @include box-shadow(rgba(white, 0.7) 0px 0px 1px, rgba(#da79f3, 0.6) 0 0px 25px 5px);
    }
}

Note that we also need to declare @-webkit-keyframes and @-moz-keyframes if we want to support all WebKit based browsers and Firefox.

Let’s now write the JavaScript magic that will create all the bricks and animate them.

We first declare a matrix of all the relative coordinates of the bricks. Each brick position depends on its predecessor. This way, it becomes very easy to change the positioning or behavior of the animation if needed. And we add the bricks to the bricks div using a loop.

var matrix = [[0,0], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], 
[0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], 
[0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [-2,-12], [-5,-12], [-5,-12], [-9,-11], [-10,-10], 
[-11,-9], [-12,-7], [-12,-5], [-12,-4], [-12,1], [-12,1], [-12,3], [-12,4], [-12,5], [-12,7], 
[-10,10], [-8,11], [-7, 11], [-3,12], [-12,5], [-12,5], [-12,6], [-11,9], [-11,9], [-10,10], 
[-6,12], [-6,11], [-5,12], [-3,12], [-1,12], [0,12], [0,12], [2,12], [4,12], [4,12], [9,10], 
[9,11], [10,10], [10,10], [11,8], [-4,12], [-2,12], [3,12], [6,12], [6,12], [11,10], [11,8], 
[12,4], [12,1], [3,12], [6,12], [10,10], [10,10], [11,7], [12,4], [12,3], [12,0], [12,-2], 
[12,-2], [12,-2], [12,-8], [10,-10], [8,-11], [7,-12]];

// Creation of the bricks
for (i=0; i<matrix.length; i++) {
  $(".bricks").append("<div class='brick displayNone'></div>");
}

Then we position the bricks, using the first brick as a reference.

// Positioning of the first brick
var currentY = 218;
var currentX = 361;

// Positioning of the rest of the bricks, using the matrix and the first brick as a reference.
for (i=0; i<matrix.length; i++) {
  currentY += matrix[i][0];
  currentX += matrix[i][1];
  var currentBrick = $(".brick")[i];
  $(currentBrick).css("top", currentY +"px");
  $(currentBrick).css("right", currentX +"px");
}

We now show the bricks one by one, with a little animation.

var x = 0;
$(".brick").each(function(index) {
  // here we calculate the timeout we'll add to each brick, so they show up one after 
  // the other, and we add a deceleration at the end to make it look better
  x += 20+(x/60);
  if(index > 80){
    x += (x/50);
  }

  var brick = $(this);
  setTimeout(function() {
    $(brick).removeClass("displayNone");
    $(brick).animate({
      top: '+=50'
    });
  }, x);
});

At the end, we illuminate the bricks using our illuminated class that uses the CSS3 animation.

setTimeout(function() {
  $(".brick").addClass("illuminated");
}, x + 500);

Then we hide all the bricks and fade in the final icon.

setTimeout(function() {
  $(".brick").fadeOut(300);
  setTimeout(function() { $(".bricks").hide(); }, 400); // this prevents some weird bugs
  $(".final_icon").fadeIn(1000);
}, x + 900);

To summarize, we’re using JavaScript to create and position the bricks using relative coordinates, and animating them using timeouts and the jQuery .animate() function, and then we use a CSS3 animation to light up the bricks before they disappear.

As an example, here’s a light version of the animation (no illumination of the bricks before showing the final icon).

Christophe Tauziet
November 9, 2012
blog comments powered by Disqus

Comments are closed.

Archives

Categories

RSS Feed Follow us Like us