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.
- slideInLeft for blog content.
- slideInRight for widget.
- 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>
HTML: Hover: Link
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 <span class="fa fa-folder"></span>
</a>
<a ...>...</a>
<a ...>...</a>
<a ...>...</a>
<a ...>...</a>
<a ...>...</a>
</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.