The AI Works community logo The Blockchain Works community logo The Functional Works community logo The Golang Works community logo The Java Works community logo The JavaScript Works community logo The Python Works community logo The Remote Works community logo The WorksHub company logo

We use cookies and other tracking technologies to improve your browsing experience on our site, analyze site traffic, and understand where our audience is coming from. To find out more, please read our privacy policy.

By choosing 'I Accept', you consent to our use of cookies and other tracking technologies.

We use cookies and other tracking technologies to improve your browsing experience on our site, analyze site traffic, and understand where our audience is coming from. To find out more, please read our privacy policy.

By choosing 'I Accept', you consent to our use of cookies and other tracking technologies. Less

We use cookies and other tracking technologies... More

Login or register
to publish this job!

Login or register
to save this job!

Login or register
to save interesting jobs!

Login or register
to get access to all your job applications!

Login or register to start contributing with an article!

Login or register
to see more jobs from this company!

Login or register
to boost this post!

Show some love to the author of this blog by giving their post some rocket fuel 🚀.

Login or register to search for your ideal job!

Login or register to start working on this issue!

Login or register
to save articles!

Login to see the application

Engineers who find a new job through JavaScript Works average a 15% increase in salary 🚀

You will be redirected back to this page right after signin

Blog hero image

Create a Distortion Effect Using GSAP

King Somto 28 March, 2022 | 7 min read

Animating DOM elements on the web has been one of the many topics with numerous solutions. We have seen the rise of HTML and CSS classic design systems, and how to structure keyframe animations accordingly. Then, we transitioned into using javascript libraries like jQuery, only to now be trumped by more efficient and performant libraries, one of which is GSAP.

Introduction

GSAP (GreenSock Animation Platform), as indicated by the Getting Started guide, “is a suite of tools for scripted animations”. What that basically means, is that it is one big ecosystem of ready-made functions and methods you can use to animate literally anything on the DOM. What makes GSAP so great, is that it is fully optimized for performance and scaling, even when building complex animation. This is what makes it trump over jQuery, as well as its minimal code style in contrast to jQuery’s robust syntax.

What will we be building?

In this article, you will learn how to build a cool-looking webpage with a distortion effect that gets triggered on hover, using GSAP and hover-effect library. This example will help us shorten the learning curve with GSAP.

animation_gsap.gif

Credits go to: UI Designer: Maxim Nilov | Dribbble Github: codicts/Fashion-Landing-Page (github.com)

Prerequisites

GSAP is a suite that makes rendering on the DOM a lot easier, and this is made possible by using a few key concepts that are related to DOM manipulation, much like every other framework for the web. To this end, you will need to know:

  • HTML, CSS and Javascript
  • Basic React

How does GSAP work?

GSAP has built-in components to help create these animations, and they come with methods that help us set the properties we want to animate. For this example, we will only need one of these components, which is the TweenMax. (Please check out their docs:).

Join our newsletter
Join over 111,000 others and get access to exclusive content, job opportunities and more!

TweenMax

The Tween and TweenMax components are one of the more widely used ones, in that they make it easy to do the simple transitions without writing complex keyframes. The tween keyword is derived from ‘between’, which basically means “change this property between a given duration from one value to another”. Let’s take a look at some of the methods that exists within GSAP:

  • gsap.to()
  • gsap.from()
  • gsap.staggerFrom()

gsap.to()

Here, we tell gsap to change the property of a given value to another as well, but in this case, we indicate the starting value of the animation. Here’s an example:

gsap.to("#logo", {duration: 1, x: 100});

Gsap.from()

Here, we tell gsap to change the property of a given value to another as well, but in this case, we indicate the starting value of the animation. Here’s an example:

gsap.from("#logo", {duration: 1, x: 100});

Gsap.staggerFrom()

Now staggerFrom works a bit differently from gsap.to() and gsap.from(). With to and from, we deal with a single HTML element that we want to animate, but what if we want to animate a group of elements, particularly children of a parent element? With staggerFrom(), we can set an animation to take effect for a group of child elements, and even set an interval or “stagger” between the elements, to give it this sequential feel as they get animated. Here’s an example of using this:

    TweenMax.staggerFrom(".media ul li", 1.5, { //TweenMax used in place of gsap
      delay: 1.5,
      opacity: 0,
      x: "-60",
      ease: Expo.easeInOut
    }, 0.08);

First, we call the gsap library (TweenMax), then we can use the “staggerFrom()” method to target the HTML <li/> elements under the media class. The value 1.5 is used to indicate the stagger to be affected between the start time of each child’s animation. This stagger is what helps the animations to have a sequential feel between them. Then we put in the properties we want for each element. Note the ease property, which you can learn more about in their documentation.

Getting Started with GSAP

Now let’s get started with building our distortion effect page. Create your folder and in that new folder, create your HTML and CSS files. Then in your HTML file, you set up your basic HTML markup.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
   
</body>
</html>
Next, our imports:
  <!-- google fonts -->
  <link href="https://fonts.googleapis.com/css?family=Poppins:500,600,700,900&display=swap" rel="stylesheet">
  <!-- css -->
  <link rel="stylesheet" href="style.css">
Then our scripts as well, for GSAP and hover-effect (these go on the bottom of the html page)
 <!-- icons -->
  <script src="https://unpkg.com/ionicons@4.5.10-0/dist/ionicons.js"></script>
  <!-- gsap -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js"
    integrity="sha256-lPE3wjN2a7ABWHbGz7+MKBJaykyzqCbU96BJWjio86U=" crossorigin="anonymous"></script>
  <!-- three js -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/108/three.min.js"
    integrity="sha256-3mBEX8I0uMLF7+AUjJeTCelosuorzYpqwBMBPDTyQqY=" crossorigin="anonymous"></script>

Next, our imports:


<!-- google fonts -->
  <link href="https://fonts.googleapis.com/css?family=Poppins:500,600,700,900&display=swap" rel="stylesheet">
  <!-- css -->
  <link rel="stylesheet" href="style.css">

Then our scripts as well, for GSAP and hover-effect (these go on the bottom of the HTML page)


<!-- icons -->
  <script src="https://unpkg.com/ionicons@4.5.10-0/dist/ionicons.js"></script>
  <!-- gsap -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js"
    integrity="sha256-lPE3wjN2a7ABWHbGz7+MKBJaykyzqCbU96BJWjio86U=" crossorigin="anonymous"></script>
  <!-- three js -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/108/three.min.js"
    integrity="sha256-3mBEX8I0uMLF7+AUjJeTCelosuorzYpqwBMBPDTyQqY=" crossorigin="anonymous"></script>

Now we are set to get started with our web page. You can set up the views to your convenience, but for this tutorial, we will first set up the main webpage.

  <!-- NAVBAR
    =============================== -->
    <nav class="navbar">
      <div class="menu">
        <ion-icon name="ios-menu"></ion-icon>
      </div>
      <div class="lang">eng</div>
      <div class="search">
        <ion-icon name="ios-search"></ion-icon>
      </div>
    </nav>
 
 
    <!-- SOCIAL MEDIA
    =============================== -->
    <div class="media">
      <ul>
        <li>facebook</li>
        <li>instagram</li>
        <li>twitter</li>
      </ul>
    </div>
 
 
    <!-- TEXT
    =============================== -->
    <div class="text">
      <h1>
        <span class="hidetext">toni&guy</span>
      </h1>
      <h2>duality</h2>
      <h3>
        <span class="hidetext">collection 2017 <br> duality</span>
      </h3>
      <p>
        <span class="hidetext">
          Lorem ipsum dolor sit amet consectetur, adipisicing elit. Unde quis, delectus facere
          neque sunt commodi quae
          culpa dolores doloribus magnam?
        </span>
      </p>
    </div>
 
 
    <!-- SPONSOR
    =============================== -->
    <div class="sponsor">
      <img src="./images/sponsor-logo.png" alt="">
      <p>official sponsor</p>
    </div>

Then the CSS for the basic webpage:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
 
body {
  font-family: 'Poppins';
  background: #D8DBE2;
  width: 100%;
  height: 100vh;
  overflow: hidden;
}
 
ul {
  list-style: none;
}
 
/* NAVBAR
=========================== */
.navbar {
  display: flex;
  justify-content: space-between;
  height: 80px;
  align-items: center;
}
 
.navbar > div {
  padding: 0 30px;
  font-size: 20px;
}
 
.navbar .menu {
  margin-right: auto;
}
 
.navbar .lang {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
}
 
 
/* SOCIAL MEDIA
=========================== */
.media ul {
  position: absolute;
  bottom: 250px;
  left: -140px;
  transform: rotate(-90deg);
}
 
.media ul li {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 2px;
  display: inline-block;
  padding: 0 30px;
}
 
 
/* TEXT
=========================== */
.text {
  position: absolute;
  top: 200px;
  left: 100px;
  transform: rotate(-90deg);
}
 
.text h1 {
  font-size: 120px;
  text-transform: uppercase;
  font-weight: 900;
  letter-spacing: -10px;
  margin-bottom: 20px;
 
  position: relative;
  overflow: hidden;
  height: 150px;
  width: 600px;
}
.text h1 .hidetext {
  position: absolute;
}
 
.text h2 {
  position: absolute;
  top: 40px;
  left: -80px;
  color: #EFDE74;
  z-index: -1;
  font-size: 150px;
  font-weight: 600;
  letter-spacing: 8px;
  text-transform: uppercase;
}
 
.text h3 {
  font-size: 40px;
  text-transform: uppercase;
  font-weight: 600;
  line-height: 1;
 
  position: relative;
  overflow: hidden;
  height: 80px;
}
.text h3 .hidetext {
  position: absolute;
}
 
.text p {
  width: 200px;
  font-size: 12px;
  margin-top: 30px;
  font-weight: 500;
 
  position: relative;
  overflow: hidden;
  height: 110px;
}
.text p .hidetext {
  position: absolute;
}
 
 
/* SPONSOR
=========================== */
.sponsor {
  position: absolute;
  right: 100px;
  bottom: 100px;
  text-align: center;
}
.sponsor img {
  width: 200px;
  transform: rotate(-90deg);
}
.sponsor p {
  margin-top: 20px;
  font-size: 12px;
  text-transform: uppercase;
  font-weight: 900;
  transform: rotate(180deg);
}

Let’s examine our webpage:

webpage_gsap.gif

Here are a few things we can see:

  • 3 squares animate from bottom to top, to reveal the webpage. Here, we already know they will be 3 divs to have a position absolute, and then we use the “to” method to animate between them.
  • Navbar above, animate from top to bottom, with changed opacity.
  • Text on the side changes from 0 to 1 and increases in height.

For the 3 squares, we create 3 divs to represent them.

    <div class="overlay first"></div>
    <div class="overlay second"></div>
    <div class="overlay third"></div>

Then we style accordingly in the styles.css

/*===========================  OVERLAY =========================== */
.overlay {
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0%;
  z-index: 99;
}
.first {
  background: #efde74;
}
.second {
  background: #efde74;
  left: 33.3%;
}
.third {
  background: #efde74;
  left: 66.6%;
}

Now we can set up our animation with GSAP:

 TweenMax.to(".first", 1.5, {
      delay: .5,
      top: "-100%",
      ease: Expo.easeInOut
    });
 
    TweenMax.to(".second", 1.5, {
      delay: .7,
      top: "-100%",
      ease: Expo.easeInOut
    });
 
    TweenMax.to(".third", 1.5, {
      delay: .9,
      top: "-100%",
      ease: Expo.easeInOut
    });

Notice that the delay has been varied by .2 to have that effect. You could also use the staggerFrom() method to vary between the children and see how the effect varies.

Next, we animate our navbar and various texts.

   // NAVBAR
    TweenMax.staggerFrom(".navbar div", 1.5, {
     
      delay: 1.5,
      opacity: 0,
      y: "20",
      ease: Expo.easeInOut
    }, 0.08);
 
    // MEDIA
    TweenMax.staggerFrom(".media ul li", 1.5, {
      delay: 1.5,
      opacity: 0,
      x: "-60",
      ease: Expo.easeInOut
    }, 0.08);
 
    // TEXT
    TweenMax.from(".text h1 .hidetext", 1.5, {
      delay: 1,
      y: "100%",
      ease: Expo.easeInOut
    });
 
    TweenMax.from(".text h3 .hidetext", 1.5, {
      delay: 1.2,
      y: "100%",
      ease: Expo.easeInOut
    });
 
    TweenMax.from(".text p .hidetext", 1.5, {
      delay: 1.3,
      y: "100%",
      ease: Expo.easeInOut
    });
 
    TweenMax.from(".text h2", 1.5, {
      delay: 1.5,
      opacity: 0,
      x: "-10000",
      ease: Expo.easeInOut
    });
 
    // SPONSOR
    TweenMax.from(".sponsor img", 1.5, {
      delay: 1.5,
      opacity: 0,
      y: "20",
      ease: Expo.easeInOut
    });
 
    TweenMax.from(".sponsor p", 1.5, {
      delay: 1.6,
      opacity: 0,
      y: "20",
      ease: Expo.easeInOut
    });

Lastly, for the distortion effect, we will make use of the hover-effect library. You can get the hover-effect library here, then copy the code, create a new file called hover-effect.umd.js and paste the code. Then we import our newly created script:

  <!-- hover-effect js -->
  <script src="./hover-effect.umd.js"></script>

Now, how our distortion effect works, is that the library will create a blur of the current image, then transition into a displacement image we will need to provide, then lastly transition to a blurred version of the second image to be transitioned into, and then set the image from a blurred state to a regular state. So first, we create a div that will represent our distortion image container.

  <!-- DISTORTION =============================== -->
    <div class="distortion"></div>

So we need to provide a displacement image, (which should look like a blur effect for convenience), and then the two images to transition between:

    new hoverEffect({
      parent: document.querySelector('.distortion'),
      intensity: 0.2,
      image1: './images/01.png',
      image2: './images/02.png',
      displacementImage: './images/diss.png',
      imagesRatio: 340 / 300   
    })

And that puts together the distortion effect with some animation.

Thanks for reading.

Discuss this article on

Related Issues

socious-io / web-app-v2
  • Started
  • 0
  • 6
  • Intermediate
  • TypeScript
socious-io / web-app-v2
socious-io / web-app-v2
  • Started
  • 0
  • 1
  • Intermediate
  • TypeScript
socious-io / web-app-v2
  • 1
  • 0
  • Intermediate
  • TypeScript
open-editions / corpus-joyce-ulysses-tei
open-editions / corpus-joyce-ulysses-tei
  • Started
  • 0
  • 24
  • Intermediate
  • HTML

Get hired!

Sign up now and apply for roles at companies that interest you.

Engineers who find a new job through JavaScript Works average a 15% increase in salary.

Start with GitHubStart with Stack OverflowStart with Email