Preface

Goal: Trigger animation on scroll using intersection observer.

The MDN explanation is good. But when I need a real life example I search.

Itzami Example

After duckduckwent for a while, I found this simple, but good example.

And that’s it!


1: Specific Observer

So how to bind the observer script to animation style class? We can modify the example above and apply to our simple need.

HTML Head

First add these two stylesheets in the HTML head.

These stylesheets is the full version, from the original repository.

  <link rel="stylesheet" type="text/css" href="css/hover.css">
  <link rel="stylesheet" type="text/css" href="css/animate.css">

Then add adapted version of the example script.

  <script src="js-72/observer-bounce.js"></script>

Javascript Skeleton

I’m using native javascript.

document.addEventListener(
  "DOMContentLoaded", function(event) { 

  let bounceObserver =
    new IntersectionObserver( (entries) => {...});

  const bouncesToObserve = document
    .querySelectorAll(".animate__observe__bounce");

  bouncesToObserve.forEach((element) => {
    bounceObserver.observe(element);
  });
});

HTML: Animation Class: No Observer

As usual, you can add zoom in animation, by adding class. but this won’t get replayed.

<div class="animate__animated animate__rubberBand"
     id="sitedesc_image"></div>

HTML: Animation Class: With Observer

The business card image, will be bounce. Try scroll the page, up and down, until the image shown after being hidden.

      <div class="justify-content-center">
        <img src="images/one-page.png"
           class="animate__animated animate__bounce
                  animate__observe__bounce"
             alt="business card">
      </div>

All I do is adding this animate__observe__bounce class.

Javascript: Bounce Observer

But how does it works?

It is simply by adding and removing class. Consider examine the detail:

  let bounceObserver =
    new IntersectionObserver( (entries) => {
      entries.forEach((entry) => {
        const cl = entry.target.classList;
        if (entry.intersectionRatio > 0) {
          cl.add('animate__bounce');
        } else {
          cl.remove('animate__bounce');
        }
      });
  });

The Issue

This approach has a few issue. I should write this long procedure for each effect. And the javascript become unbearable longer.


2: Generic Observer

However this can enhance the script above to make a generic one.

HTML Head

Just change the javascript into our final form.

  <script src="js/animate-observer.js"></script>

What effect?

First to do is to write down all selected effect in an array. Only what I might need, and exclude the rest. This means you can write down your own effect.

  const effects = [
    'bounce', 'rubberBand', 'wobble', 'swing',
    'rollIn', 'zoomIn', 'flash', 'flip', 'pulse',
    'slideInLeft', 'slideInRight', 'headShake'
  ];

Javascript Skeleton

I’m still using native javascript, as usual.

document.addEventListener(
  "DOMContentLoaded", function(event) { 

  // only what I might need, and exclude the rest.
  const effects = [...];

  let elementObserver =
    new IntersectionObserver( (entries) => {...});

  const elementsToObserve = document
    .querySelectorAll(".animate__observe");

  elementsToObserve.forEach((element) => {
    elementObserver.observe(element);
  });
});

HTML: Animation Data

Instead of class, I store the animation name in dataset. So we can have different effect freely.

For example, this use rubberBand animation.

<div class="animate__animated animate__observe"
     data-animate="rubberBand"
     id="sitedesc_image"></div>

And this one use bounce animation.

  <div class="justify-content-center">
    <img src="images/one-page.png"
       class="animate__animated animate__observe"
data-animate="bounce"
         alt="business card">
  </div>

Note that I still need to add this animate__observe class.

Javascript: Element Observer

But how does it works?

It is simply by adding and removing class, based on the stored dataset.

Consider examine the detail:

  let elementObserver =
    new IntersectionObserver( (entries) => {
      entries.forEach((entry) => {
        const el = entry.target;
        const animate = el.dataset.animate;

        if (effects.includes(animate)) {
          const effect = 'animate__' + animate;

          if (entry.intersectionRatio > 0) {
            el.classList.add(effect);
          } else {
            el.classList.remove(effect);
          }
        }
      });
  });

Preview

Enjoy the result


3: Animating Widget

Apply to other page as well.

One of my favorite is animating the whole blog page. A blog page consist of the content and the widget.

I usually use zoomIn effect, but for this tutorial purpose, I will use slide-in effect.

  1. slideInLeft for blog content.
  2. slideInRight for widget.
  3. Addtional hover effect.

HTML Head

No changed.

HTML: Animate: Blog Content

The whole main tag.

    <main role="main"
          class="column is-two-thirds
                 animate__animated animate__observe"
          data-animate="slideInLeft">
      ...
    </main>

HTML: Animate: Widget

For each section inside aside tag.

    <aside class="column is-one-thirds">

      <section class="aside-wrapper green
                      animate__animated animate__observe"
        data-animate="slideInRight">
        ...
      </section>

      <section class="aside-wrapper deep-orange
                      animate__animated animate__observe"
        data-animate="slideInRight">
        ...
      </section>

    </aside>

hvr-underline-from-left

No need any observer.

<div class="widget-body">
  <ul class="widget-list">
    <li><a href="http://epsi-rns.github.io/"
          class="hvr-underline-from-left"
         >Linux/BSD Desktop Customization</a></li>
    <li><a href="http://epsi-rns.gitlab.io/"
          class="hvr-underline-from-left"
         >Web Development Blog</a></li>
    <li><a href="http://oto-spies.info/"
          class="hvr-underline-from-left"
         >Car Painting and Body Repair.</a></li>
  </ul>
</div>

HTML: Hover: Tag

hvr-buzz

No need any observer.

<div class="widget-body">

  <a class="tag is-small is-dark hvr-buzz
            deep-orange z-depth-1 hoverable p-b-5"
      href="https://epsi-rns.gitlab.io/categories/backend"
    >backend&nbsp;<span class="fa fa-folder"></span>
  </a>&nbsp;
  <a ...>...</a>&nbsp;
  <a ...>...</a>&nbsp;
  <a ...>...</a>&nbsp;
  <a ...>...</a>&nbsp;
  <a ...>...</a>&nbsp;
</div>

Preview

Enjoy the result


What is Next ?

How about other example? Of course I have example in my mind, that I can share.

Consider continue reading [ Animation Observer - Part Three ].

Thank you for reading.