Intersection Observerを使った
アニメーションデモページ

head

                               
// IE11対策用のpolyfillの読み込み
<script src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver"></script>
                               
                           

js

                               
var option = {
root: null,
rootMargin: "0% 0% -20% 0%",
threshold: 0.2,
};
// 交差した際の処理を記載
var callback = function (entries) {
entries.forEach(function (entry) {

if (entry.intersectionRatio > 0.2) {

var targets = entry.target.getElementsByClassName("demo__block");
var targetsArray = Array.prototype.slice.call(targets, 0);

targetsArray.forEach(function (item) {
var targetClassList = item.classList;

if( targetClassList.contains('is-fade_in_side') == true ){
targetClassList.add("is-fade_in_side--done");
} else if (targetClassList.contains('is-fade_in_updown') == true) {
targetClassList.add("is-fade_in_updown--done");
} else if(targetClassList.contains('is-fade_in_zoom') == true){
targetClassList.add("is-fade_in_zoom--done");
} else if(targetClassList.contains('is-bounce') == true){
var itemChildren = item.children;
var itemChildrenArray = Array.prototype.slice.call(itemChildren, 0);

itemChildrenArray.forEach(function (el, i) {
(function (index) { //indexにiが代入される
setTimeout(function () {
el.classList.add("is-bounce--done");
}, index * 80);
})(i);

});
}
});

observeres.unobserve(entry.target);
}
});
};
var observeres = new IntersectionObserver(callback, option);

var trigger = document.querySelectorAll(".js-trigger");
var triggerArray = Array.prototype.slice.call(trigger, 0);

triggerArray.forEach(function (el) {
observeres.observe(el);
});

                               
                           

Sass

                               
/* アニメーションを使うため先にベンダープレフィックスを定義
–––––––––––––––––––––––––––––––––––––––––––––––––– */

@mixin keyframes($animation-name: animation) {
@-webkit-keyframes #{$animation-name} {
@content;
}
@keyframes #{$animation-name} {
@content;
}
}

/* アニメーションを使うため上とセット
–––––––––––––––––––––––––––––––––––––––––––––––––– */

@mixin animation($animation-name) {
-webkit-animation: $animation-name;
animation: $animation-name;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
@keyframes fade-in-right {
0% {
//transform: translateX(100px);
transform: translate3d(100px, 0, 0);
opacity: 0;
}
100% {
//transform: translateX(0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
}

@keyframes fade-in-left {
0% {
//transform: translateX(-100px);
transform: translate3d(-100px, 0, 0);
opacity: 0;
}
100% {
//transform: translateX(0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
@keyframes fade-in-up {
0% {
//transform: translateY(-100px);
transform: translate3d(0, -100px, 0);
opacity: 0;
}
100% {
//transform: translateY(0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
@keyframes fade-in-down {
0% {
//transform: translateY(100px);
transform: translate3d(0, 100px, 0);
opacity: 0;
}
100% {
//transform: translateY(0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
@keyframes fade-in-zoom {
0% {
filter: blur(3px);
transform: scale(1.2);
opacity: 0;
}
100% {
filter: blur(0);
transform: scale(1);
opacity: 1;
}
}

@keyframes bounce {
from,
60%,
75%,
90%,
to {
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}

from {
opacity: 0;
-webkit-transform: translate3d(0, 3000px, 0);
transform: translate3d(0, 3000px, 0);
}

60% {
opacity: 1;
-webkit-transform: translate3d(0, -20px, 0);
transform: translate3d(0, -20px, 0);
}

75% {
-webkit-transform: translate3d(0, 10px, 0);
transform: translate3d(0, 10px, 0);
}

90% {
-webkit-transform: translate3d(0, -5px, 0);
transform: translate3d(0, -5px, 0);
}

to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
}

/* クラスを定義
–––––––––––––––––––––––––––––––––––––––––––––––––– */

%opacity {
opacity: 0;
}
%no-opacity {
opacity: 1;
}

.is-fade_in_side {
@extend %opacity;
}
.is-fade_in_side.is-fade_in_side--done {
@extend %no-opacity;
.demo__img {
&:first-child {
@include animation(fade-in-left 1s ease 0s);
}
&:last-child {
@include animation(fade-in-right 1s ease 0s);
}
}
}

.is-fade_in_updown {
@extend %opacity;
}
.is-fade_in_updown.is-fade_in_updown--done {
@extend %no-opacity;
.demo__img {
&:first-child {
@include animation(fade-in-up 1s ease 0.1s);
}
&:last-child {
@include animation(fade-in-down 1s ease 0.1s);
}
}
}

.is-fade_in_zoom {
@extend %opacity;
}
.is-fade_in_zoom.is-fade_in_zoom--done {
@extend %no-opacity;
.demo__img {
@include animation(fade-in-zoom 1s ease 0.1s);
}
}

.is-bounce {
.demo__img {
@extend %opacity;
}
.demo__img.is-bounce--done {
@include animation(bounce 0.3s ease);
}
}

                               
                           

HTML

                           
<div class="demo">
<div class="demo__container">
<section class="demo__section js-trigger">
<div class="demo__section_inner">
<div class="demo__block is-fade_in_side">
<div class="demo__img">
<img src="./images/observer-img03.jpg" alt="" />
</div>
<div class="demo__img">
<img src="./images/observer-img04.jpg" alt="" />
</div>
</div>
</div>
</section>
<section class="demo__section demo__section--bgcolor js-trigger">
<div class="demo__section_inner">
<div class="demo__block is-fade_in_updown">
<div class="demo__img">
<img src="./images/observer-img01.jpg" alt="" />
</div>
<div class="demo__img">
<img src="./images/observer-img02.jpg" alt="" />
</div>
</div>
</div>
</section>
<section class="demo__section js-trigger">
<div class="demo__section_inner">
<div class="demo__block is-fade_in_zoom">
<div class="demo__img">
<img src="./images/observer-img03.jpg" alt="" />
</div>
<div class="demo__img">
<img src="./images/observer-img04.jpg" alt="" />
</div>
</div>
</div>
</section>
<section class="demo__section js-trigger demo__section--bgcolor">
<div class="demo__section_inner">
<div class="demo__block demo__block--small is-bounce">
<div class="demo__img">
<img src="./images/observer-img03.jpg" alt="" />
</div>
<div class="demo__img">
<img src="./images/observer-img04.jpg" alt="" />
</div>
<div class="demo__img">
<img src="./images/observer-img02.jpg" alt="" />
</div>
<div class="demo__img">
<img src="./images/observer-img01.jpg" alt="" />
</div>
<!-- 残りのdemo__imgは省略 -->
</div>
</div>
</section>

</div>
</div>