#TECH

The modern way to implement animations in web using GSAP and ScrollMagic

The trend of web animations started with GIF animations and at that time it was the easiest way of implementing animations on the web.

But, the problem with GIF is that it doesn’t have variable transparency and doesn’t support an alpha channel. Therefore, all pixels are either fully opaque or completely transparent.

The dawn of flash web animations

After the GIFs, came Flash web animations which brought new capabilities, like animations with sound and interactivity. 

But there is a downside to this approach as well.

1.) This approach requires a flash plugin installed on the browser to run. 

2.) It doesn’t run well on mobile devices.

Web animation today

Today, we have different needs for web animations. The animation should be smooth, light, interactive, and ought to work on all devices.

For that, HTML5, CSS3, JavaScript, and SVG (scalable graphics) seem to be the best solution (for web animation). Using these modern web technologies and languages will help tackle most, but not all, of the above problems. 

Why animations are important for the user experience?

Web animation can engage and hold people’s attention longer than a static web page and help communicate an idea or concept more clearly and effectively. Excellent web animation conveys a story behind every bit of movement. It’s all about bringing animation to life with meaning and “soul”.

Web animation should be smooth, meaningful, and support the visitor’s journey. The web designer/animator needs to be aware of how the animation fits into the user experience, try to predict likely user flows, and then support it in a meaningful way.

GSAP + ScrollMagic Animation – VanillaJs

This blog is for all those UI developers who saw those elegant and cool SVG/UI animations online and wondered– what is this crazy shit? How can I implement this in my code?

Well, don’t worry, this article will help you with that.

In this blog, we will discuss & learn about the two powerful animation libraries, GSAP (Greensock Animation API) & ScrollMagic. With the help of these two libraries, one can create complex (yet elegant) animations.  

So let’s start right away. We will create a sushi animation that will help us understand the working of GSAP & Scrollmagic.

CodeSandbox link: https://codesandbox.io/s/sushi-animation-vanilla-js-2pcei?fontsize=14&hidenavigation=1&theme=dark

sushi-animation-16|9

Steps that we will be following:

  1. File/Folder structure for Sushi animation project
  2. Include GSAP in your project
  3. Include ScrollMagic in your project
  4. Intro to GSAP & its usage in the project
  5. Intro to ScrollMagic & its usage in the project

File/Folder structure

  1. Create a new folder with the name sushi-animation. Then create index.html, main.js, styles.css files inside the sushi animation folder.
  2. Copy & paste below code in your index.html file.
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8" />
      <meta content="width=device-width, initial-scale=1.0" name="viewport" />
      <meta content="ie=edge" http-equiv="X-UA-Compatible" />
      <title>Sushi Animation - GSAP & Scrollmagic</title>
      <link href="src/styles.css" rel="stylesheet" />
    </head>
    <body>
    <div class="sushi-animation">
      <!--Sushi SVG-->
    </div>
    <!--Local Script-->
    <script src="src/index.js"></script>
    </body>
    </html>
    
  3. Copy & paste below code in your styles.css
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    body {
      margin: 0;
      background: #ffd23f;
      height: 100%;
      overflow: hidden;
    }
    
    .sushi-animation {
      display: flex;
      align-items: center;
      justify-content: center;
      flex-direction: column;
      width: 100%;
      height: 100vh;
      border: 10px solid #FDCB29;
      box-sizing: border-box;
    }
    .sushi-animation svg {
      width: 100%;
    }
    .sushi-animation .heading {
      color: #000;
      font-family: raleway, sans-serif;
      font-size: 2rem;
      text-align: center;
      width: 100%;
    }
    
  4. Copy the SVG code from sushi-animation.svg file& paste it inside sushi-animation div.
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    <div class="sushi-animation">
    	<svg xmlns="http://www.w3.org/2000/svg" width="1181" height="595" viewBox="0 0 1181 595">
    		<g id="sushi" transform="translate(-93 -86)">
    			<rect id="frame" width="1181" height="595" transform="translate(93 86)" fill="none"/>
    			<circle id="bg-01" cx="177" cy="177" r="177" transform="translate(394 186)" fill="#f3fcf0" opacity="0.11"/>
    			<circle id="bg-02" cx="54" cy="54" r="54" transform="translate(866 186)" fill="#f3fcf0" opacity="0.11"/>
    			<g id="bowl" transform="translate(15 27)">
    				<path id="Path_7" data-name="Path 7" d="M637.812,458.906s52.01,49.079,94.922,66.775,120.291,34.031,165.456,25.545,40.848-52.973,7.524-73.964S763.962,440.672,740.978,451.5s-62.3,16.651-62.3,16.651Z" opacity="0.095"/>
    				<g id="Group_1" data-name="Group 1" transform="translate(78.005 66.923)">
    					<path id="Path_1" data-name="Path 1" d="M604,401.038c-37.5,0-57.444-11.641-75-42.046-19.989-27.228-100-100-100-100s-2.043-25.6,175-25,175,25,175,25-81.83,71.85-100,100S643.047,401.936,604,401.038Z" transform="translate(-0.001)" fill="none" stroke="#1f271b" stroke-linecap="round" stroke-linejoin="round" stroke-width="10"/>
    					<path id="Path_2" data-name="Path 2" d="M429,273s-3.055,25,175,25,175-25,175-25" transform="translate(0 -14.006)" fill="none" stroke="#1f271b" stroke-width="10"/>
    				</g>
    			</g>
    			<path id="chopstick-02" d="M6.3,259.738V0c5.983,0,6.3,14.393,6.3,14.393S9.984,242.467,8.608,251.987c-1,6.941-1.772,7.881-2.115,7.881a.248.248,0,0,1-.193-.13Zm-2.311-7.751C2.611,242.467,0,14.393,0,14.393S.315,0,6.3,0V259.738a.248.248,0,0,1-.2.13c-.341,0-1.11-.94-2.113-7.881Z" transform="translate(927.733 214.295) rotate(43)" fill="#1f271b"/>
    			<path id="chopstick-01" d="M6.3,259.738V0c5.983,0,6.3,14.393,6.3,14.393S9.984,242.467,8.608,251.987c-1,6.941-1.772,7.881-2.115,7.881a.248.248,0,0,1-.193-.13Zm-2.311-7.751C2.611,242.467,0,14.393,0,14.393S.315,0,6.3,0V259.738a.248.248,0,0,1-.2.13c-.341,0-1.11-.94-2.113-7.881Z" transform="matrix(0.848, 0.53, -0.53, 0.848, 871.709, 186.214)" fill="#1f271b"/>
    			<g id="sushi-01"
    			   transform="matrix(0.899, 0.438, -0.438, 0.899, 345, 345)">
    				<g id="Union_3" data-name="Union 3" transform="translate(312 78)">
    					<path id="Path_1-2" data-name="Path 1" d="M22.783,34.467A68.972,68.972,0,0,1,6.794,32.811a18.4,18.4,0,0,1-4.749-1.758C1.34,30.635.5,29.986.5,29.263A.976.976,0,0,1,.514,29.1l.1-.584H.5V5.7c0-.723.84-1.373,1.545-1.79A18.4,18.4,0,0,1,6.794,2.156,68.972,68.972,0,0,1,22.783.5,68.974,68.974,0,0,1,38.772,2.156a18.4,18.4,0,0,1,4.749,1.758c.7.417,1.545,1.066,1.545,1.79V28.515h-.114l.1.584a.976.976,0,0,1,.014.164c0,.723-.84,1.373-1.545,1.79a18.4,18.4,0,0,1-4.749,1.758A68.974,68.974,0,0,1,22.783,34.467Z" fill="#1f271b"/>
    					<path id="Path_2-2" data-name="Path 2" d="M22.783,33.967A68.47,68.47,0,0,0,38.65,32.326c4.68-1.172,5.916-2.516,5.916-3.063a.468.468,0,0,0-.007-.08l-.2-1.168h.206V5.7c0-.547-1.236-1.892-5.916-3.063A68.47,68.47,0,0,0,22.783,1,68.468,68.468,0,0,0,6.916,2.641C2.236,3.812,1,5.157,1,5.7V28.015h.206l-.2,1.168a.467.467,0,0,0-.007.08c0,.547,1.236,1.892,5.916,3.063a68.468,68.468,0,0,0,15.867,1.641m0,1C10.2,34.967,0,32.413,0,29.263a1.471,1.471,0,0,1,.021-.248H0V5.7C0,2.554,10.2,0,22.783,0S45.566,2.554,45.566,5.7V29.015h-.021a1.47,1.47,0,0,1,.021.248C45.566,32.413,35.366,34.967,22.783,34.967Z" fill="#707070"/>
    				</g>
    				<g id="Ellipse_3" data-name="Ellipse 3" transform="translate(317.094 80.547)" fill="#fff" stroke="#707070" stroke-width="1">
    					<ellipse cx="17.83" cy="4.245" rx="17.83" ry="4.245" stroke="none"/>
    					<ellipse cx="17.83" cy="4.245" rx="17.33" ry="3.745" fill="none"/>
    				</g>
    			</g>
    			<g id="sushi-02"
    			   transform="matrix(0.788, -0.616, 0.616, 0.788, 380, 370)">
    				<g id="Union_3-2" data-name="Union 3" transform="translate(312 78)">
    					<path id="Path_3" data-name="Path 3" d="M22.783,34.467A68.972,68.972,0,0,1,6.794,32.811a18.4,18.4,0,0,1-4.749-1.758C1.34,30.635.5,29.986.5,29.263A.976.976,0,0,1,.514,29.1l.1-.584H.5V5.7c0-.723.84-1.373,1.545-1.79A18.4,18.4,0,0,1,6.794,2.156,68.972,68.972,0,0,1,22.783.5,68.974,68.974,0,0,1,38.772,2.156a18.4,18.4,0,0,1,4.749,1.758c.7.417,1.545,1.066,1.545,1.79V28.515h-.114l.1.584a.976.976,0,0,1,.014.164c0,.723-.84,1.373-1.545,1.79a18.4,18.4,0,0,1-4.749,1.758A68.974,68.974,0,0,1,22.783,34.467Z" fill="#1f271b"/>
    					<path id="Path_4" data-name="Path 4" d="M22.783,33.967A68.47,68.47,0,0,0,38.65,32.326c4.68-1.172,5.916-2.516,5.916-3.063a.468.468,0,0,0-.007-.08l-.2-1.168h.206V5.7c0-.547-1.236-1.892-5.916-3.063A68.47,68.47,0,0,0,22.783,1,68.468,68.468,0,0,0,6.916,2.641C2.236,3.812,1,5.157,1,5.7V28.015h.206l-.2,1.168a.467.467,0,0,0-.007.08c0,.547,1.236,1.892,5.916,3.063a68.468,68.468,0,0,0,15.867,1.641m0,1C10.2,34.967,0,32.413,0,29.263a1.471,1.471,0,0,1,.021-.248H0V5.7C0,2.554,10.2,0,22.783,0S45.566,2.554,45.566,5.7V29.015h-.021a1.47,1.47,0,0,1,.021.248C45.566,32.413,35.366,34.967,22.783,34.967Z" fill="#707070"/>
    				</g>
    				<g id="Ellipse_3-2" data-name="Ellipse 3" transform="translate(317.094 80.547)" fill="#fff" stroke="#707070" stroke-width="1">
    					<ellipse cx="17.83" cy="4.245" rx="17.83" ry="4.245" stroke="none"/>
    					<ellipse cx="17.83" cy="4.245" rx="17.33" ry="3.745" fill="none"/>
    				</g>
    			</g>
    		</g>
    	</svg>
    	<h1 class="heading">Your Sushi is Ready 😊</h1>
    </div>
    

Include GSAP in your project

Add GSAP CDN link in your project 

1
2
<!--GSAP Library-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.0.4/gsap.min.js"></script>

Include ScrollMagic in your project

Add ScrollMagic CDN link in your project 

1
2
3
<!--ScrollMagic Library-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.6/ScrollMagic.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.6/plugins/animation.gsap.min.js"></script>

 

GSAP & its usage in the project

Greensock Animation Platform(GSAP) is a JS library from which you can create seamless & custom configurable animations for your web-based products.

What is the timeline in GSAP?

Timeline manages the sequencing & timing of the events in an efficient way by acting as a container for tweens & other timelines.

Create GSAP timeline with default options.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
/**
 * GSAP Docs
 * @ref: https://greensock.com/docs/
 */
const timeline = new gsap.timeline({
	defaults: {
		duration: 1, // sets the default duration of each tween to 1s
		transformOrigin: "center", // sets default transform-origin to center
		ease: 'ease', // sets the default animation timeline to ease
	},
});
What are tweens in GSAP?

A tween provides a single movement in animation.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/** 
 * @docs
 * methods: from, to, fromTo, etc
 * elementReference: class, id or tag name
 * vars: css attributes you want to change with time
 */
gsap.method(elementReference, vars)

// EXAMPLE: 
// WITHOUT Timelines (only using tweens with delays):
gsap.from("#sushi-01", {
 duration: 0.4,
 opacity: 0,
 y: "-=100",
 rotation: -70,
 ease: Bounce.easeOut
})

// WITH Timelines (cleaner, more versatile)
// 1.) Create timeline
const timeline = new gsap.timeline({
 defaults: {
   duration: 1,
   transformOrigin: "center",
   ease: "ease"
 }
});
// 2.) Add Tween into the timeline
timeline.from("#sushi-01", {
   duration: 0.4,
   opacity: 0,
   y: "-=100",
   rotation: -70,
   ease: Bounce.easeOut
 })

Now, we have to add tweens in our GSAP timeline

Use GSAP in Sushi Animation Project

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
const timeline = new gsap.timeline({
 defaults: {
   duration: 1,
   transformOrigin: "center",
   ease: "ease"
 }
});
 
timeline
 .from("#bg-01", {
   x: "-=500",
   opacity: 0
 })
 .from(
   "#bg-02",
   {
     x: "+=500",
     opacity: 0
   },
   "-=1"
 )
 .from("#bowl", {
   x: -190,
   opacity: 0
 })
 .from("#sushi-01", {
   duration: 0.4,
   opacity: 0,
   y: "-=100",
   rotation: -70,
   ease: Bounce.easeOut
 })
 .from(
   "#sushi-02",
   {
     duration: 0.4,
     opacity: 0,
     y: "-=100",
     rotation: 70,
     ease: Bounce.easeOut
   },
   "-=0.2"
 )
 .from(
   "#chopstick-01",
   {
     duration: 0.4,
     y: -250,
     opacity: 0,
     rotation: 20
   },
   "-=.4"
 )
 .from(
   "#chopstick-02",
   {
     duration: 0.4,
     y: -250,
     opacity: 0,
     rotation: 0
   },
   "-=.4"
 )
 .from(".heading", {
   y: 200,
   opacity: 0
 });

At this point, your sushi is ready with GSAP Animation. 

If you want to play your animation infinitely then you can add repeat: -1 parallel to the default options in the timeline.

1
2
3
4
5
6
7
8
const timeline = new gsap.timeline({
 defaults: {
   duration: 1,
   transformOrigin: "center",
   ease: "ease"
 },
 repeat: -1 // Repeat your animation infinitely
});

But it’s not over yet, we have one more thing to do 😉

Remember ScrollMagic?? 

Yes, now we are going to implement ScrollMagic on GSAP.

Now you must be wondering what ScrollMagic is and why we are using it ??

ScrollMagic & its usage in the project

ScrollMagic is a Javascript library that plays animations on scroll or scrollbar.

Sounds interesting, huh?

Usage in Sushi Animation Project

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/**
 * Scrollmagic Docs
 * @ref: http://scrollmagic.io/docs/index.html
 */

// Initialize ScrollMagic Controller
const controller = new ScrollMagic.Controller(); 

// Initialise ScrollMagic Scene
const scene = new ScrollMagic.Scene({ 
	triggerElement: ".sushi-animation",
	triggerHook: 'onLeave',
	duration: "100%"
})
.setPin(".sushi-animation") // This method will pin your scene in which the animation is playing
.setTween(timeline) // This method will bind our GSAP Animation with our ScrollMagic Scene
.addTo(controller); // This method will add the ScrollMagic controller into our ScrollMagic scene

 

Finally, your Sushi is ready 😋. 

Now can cook delicious sushi by just scrolling into the browser.

CodeSandbox Link:- (https://codesandbox.io/s/sushi-animation-vanilla-js-2pcei?fontsize=14&hidenavigation=1&theme=dark)

Reference links

Want to implement these libraries in your ReactJs & Angular Project? 

You will find the source code below:

ReactJs – https://github.com/Personal-Practise-Projects/43-Animations/tree/master/03-ReactJs

Angular – https://github.com/Personal-Practise-Projects/43-Animations/tree/master/02-Angular