GSAPで自動アニメーションとホバーアクションを複合させたい!!
ということで今回はGSAPで自動アニメーションとホバーアクションを複合させる実装をご紹介します!
文字にすると伝わり辛いので、詳細は上記動画を見ていただくとわかりやすいと思います!
GSAPで自動アニメーションとホバーアクションを複合させる
では今回のやりたい実装をまとめてみます。
文字化すると実装のヒントになるのでオススメです!
・約3秒の間隔で、自動でアニメーションが流れる
・自動アニメーションの内容は、①→②→③と数字が現れるものと
それと合わせて横並びの数字も遷移かつ背景色がオレンジになる
・横並びの数字はホバーすると背景色がオレンジになる
・ホバーに合わせて①~③の数字もホバーの数字と連携して現れる
・ホバー中は自動アニメーションは停止
・ホバーを外すと、再び自動アニメーションが開始する
まずは完成のコードをご覧ください!
See the Pen ブログ用 自動アニメーション&ホバー by そす (@Sosgoyo) on CodePen.
HTMLとCSSはそこまで難しい実装ではありません。
JavaScriptでクラスの付け外し(is-active)を行いますので、CSSでは
その時のプロパティを設定しておきます。今回はこんなCSSですね↓
【CSS】
.number1.is-active,
.number2.is-active,
.number3.is-active {
background-color: orange;
}
.card1.is-active,
.card2.is-active,
.card3.is-active {
display: block;
}
「is-active」の有無で行っていることは2つだけです。
JavaScript(GSAP)はこんな感じ↓
【JavaScript】
let card1 = document.querySelector('.card1');
let card2 = document.querySelector('.card2');
let card3 = document.querySelector('.card3');
let num1 = document.querySelector('.number1');
let num2 = document.querySelector('.number2');
let num3 = document.querySelector('.number3');
let tl1 = gsap.timeline();
let tl2 = gsap.timeline();
let tl3 = gsap.timeline();
let tl = gsap.timeline({
repeat: -1
});
tl
.to(card1,{className:'card1 is-active'})
.to(card2,{className:'card2'},'<')
.to(card3,{className: 'card3'},'<')
.to(num1,{className: 'number1 is-active'},'<')
.to(num2,{className: 'number2'},'<')
.to(num3,{className: 'number3'},'<')
.to(card1,{autoAlpha:1})
.to(card1,{autoAlpha:0}, '+=3')
.to(card1,{className:'card1'})
.to(card2,{className:'card2 is-active'},'<')
.to(card3,{className: 'card3'},'<')
.to(num1,{className: 'number1'},'<')
.to(num2,{className: 'number2 is-active'},'<')
.to(num3,{className: 'number3'},'<')
.to(card2,{autoAlpha:1})
.to(card2,{autoAlpha:0}, '+=3')
.to(card1,{className:'card1'})
.to(card2,{className:'card2'},'<')
.to(card3,{className: 'card3 is-active'},'<')
.to(num1,{className: 'number1'},'<')
.to(num2,{className: 'number2'},'<')
.to(num3,{className: 'number3 is-active'},'<')
.to(card3,{autoAlpha:1})
.to(card3,{autoAlpha:0}, '+=3')
num1.addEventListener('mouseover',function(){
if(tl1.isActive()){
return;
}else{
tl.pause();
tl1
.to(card1,{className:'card1 is-active'})
.to(card2,{className:'card2'},'<')
.to(card3,{className: 'card3'},'<')
.to(num1,{className: 'number1 is-active'},'<')
.to(num2,{className: 'number2'},'<')
.to(num3,{className: 'number3'},'<')
.fromTo(card1,{autoAlpha:0},{autoAlpha:1})
}
})
num2.addEventListener('mouseover',function(){
if(tl2.isActive()){
return;
}else{
tl.pause();
tl2
.to(card1,{className:'card1'})
.to(card2,{className:'card2 is-active'},'<')
.to(card3,{className: 'card3'},'<')
.to(num1,{className: 'number1'},'<')
.to(num2,{className: 'number2 is-active'},'<')
.to(num3,{className: 'number3'},'<')
.fromTo(card2,{autoAlpha:0},{autoAlpha:1})
}
})
num3.addEventListener('mouseover',function(){
if(tl3.isActive()){
return;
}else{
tl.pause();
tl3
.to(card1,{className:'card1'})
.to(card2,{className:'card2'},'<')
.to(card3,{className: 'card3 is-active'},'<')
.to(num1,{className: 'number1'},'<')
.to(num2,{className: 'number2'},'<')
.to(num3,{className: 'number3 is-active'},'<')
.fromTo(card3,{autoAlpha:0},{autoAlpha:1})
}
})
num1.addEventListener('mouseleave',function(){
tl.restart();
});
num2.addEventListener('mouseleave',function(){
tl.restart();
});
num3.addEventListener('mouseleave',function(){
tl.restart();
});
長いですね。
では少しずつご説明していきましょう!!
GSAPアニメーションの説明
timelineの設定
まずは「timeline」の設定です。
【GSAP】
let tl1 = gsap.timeline();
let tl2 = gsap.timeline();
let tl3 = gsap.timeline();
let tl = gsap.timeline({
repeat: -1
});
ここでは4つの「timeline」を設定しています。
「tl」に関しては「repeat: -1」を設定しております。
「repeat: -1」は、自動アニメーション用で設定したアニメーションが繰りかえされます。
自動アニメーションの実装
tl
.to(card1,{className:'card1 is-active'})
.to(card2,{className:'card2'},'<')
.to(card3,{className: 'card3'},'<')
.to(num1,{className: 'number1 is-active'},'<')
.to(num2,{className: 'number2'},'<')
.to(num3,{className: 'number3'},'<')
.to(card1,{autoAlpha:1})
.to(card1,{autoAlpha:0}, '+=3')
ここで説明するのはclassName
というプロパティです。className
は、HTML要素のクラス属性を設定または取得するためのJavaScriptプロパティです。
className
プロパティは、HTML要素のクラス属性全体を上書きします。
つまり、クラス属性に含まれていた全てのクラスが削除され、新しいクラスが追加されます。
ここでやっている動きとしては
・.card1というクラス属性が付いているHTML要素に「.card1 is-active」というクラスを付ける
・.card2というクラス属性が付いているHTML要素に「.card2」というクラスを付ける
・.card3というクラス属性が付いているHTML要素に「.card3」というクラスを付ける
・.number1というクラス属性が付いているHTML要素に「.number1 is-active」というクラスを付ける
・.number2というクラス属性が付いているHTML要素に「.number2」というクラスを付ける
・.number3というクラス属性が付いているHTML要素に「.number3」というクラスを付ける
です。
・.card2というクラス属性が付いているHTML要素に「.card2」というクラスを付ける というのは
ムダに見えるかもしれませんが、「.card2」に「is-active」が付いていた場合は上書きして
「.card2」のみにします。結果として「is-active」を外す動きになります。
ここまでの実装で、「.card1」と「.number1」に「is-active」クラスが付与されました。
「is-active」が付いたことで、
「.card1.isactive」・・・ display: none; ⇒ display: block;
「.number.is-acitve」・・・ background-color: white; ⇒ background-color: orange;
となりました。ですがこのままだと「.card1」は何も表示されません。
それは、「.card1」には「opacity: 0;」と「visibility: hidden;」が設定されているためです。
そこで最後に下記のコードを追記します↓
.to(card1,{autoAlpha:1})
.to(card1,{autoAlpha:0}, '+=3')
autoAlphaで表示して、表示された3秒後にautoAlphaを0にして非表示にします。
(GSAPの基本的な使い方はコチラの記事)
なぜこの一手間を加えているか??
それは、数字をフワッと表示させるためです。
上記一手間を加えず、display: block;だけで表示させるとこうなります↓
See the Pen ブログ用 自動アニメーション&ホバー by そす (@Sosgoyo) on CodePen.
どうでしょうか?
消えるときは「autolpha:0;」にしているのでフワッと消えていますが
出現時は切り替わると同時に現れてますね。
この出現時のフワッと感出すために、一旦「display:block;」にして要素を出現させ、
その直後に、消えているテキストを「autoAlpha:1」で出現させる、という流れです。
あとは「card2」と「card3」用にコードを足していくだけです。
こんな感じ↓
tl
//card1用
.to(card1,{className:'card1 is-active'})
.to(card2,{className:'card2'},'<')
.to(card3,{className: 'card3'},'<')
.to(num1,{className: 'number1 is-active'},'<')
.to(num2,{className: 'number2'},'<')
.to(num3,{className: 'number3'},'<')
.to(card1,{autoAlpha:1})
.to(card1,{autoAlpha:0}, '+=3')
//card2用
.to(card1,{className:'card1'})
.to(card2,{className:'card2 is-active'},'<')
.to(card3,{className: 'card3'},'<')
.to(num1,{className: 'number1'},'<')
.to(num2,{className: 'number2 is-active'},'<')
.to(num3,{className: 'number3'},'<')
.to(card2,{autoAlpha:1})
.to(card2,{autoAlpha:0}, '+=3')
//card3用
.to(card1,{className:'card1'})
.to(card2,{className:'card2'},'<')
.to(card3,{className: 'card3 is-active'},'<')
.to(num1,{className: 'number1'},'<')
.to(num2,{className: 'number2'},'<')
.to(num3,{className: 'number3 is-active'},'<')
.to(card3,{autoAlpha:1})
.to(card3,{autoAlpha:0}, '+=3')
これで自動アニメーションは実装完了です!
ホバーアニメーションを実装する
さあ、次はホバーアクションを実装していきます。
もう一度アニメーションの流れをおさらいしておきましょう!
・約3秒の間隔で、自動でアニメーションが流れる
・自動アニメーションの内容は、①→②→③と数字が現れるものと
それと合わせて横並びの数字も遷移かつ背景色がオレンジになる
・横並びの数字はホバーすると背景色がオレンジになる
・ホバーに合わせて①~③の数字もホバーの数字と連携して現れる
・ホバー中は自動アニメーションは停止
・ホバーを外すと、再び自動アニメーションが開始する
上記赤文字の箇所の実装ですね!!
ではコードを見ていきましょう↓
let num1 = document.querySelector('.number1');
num1.addEventListener('mouseover',function(){
if(tl1.isActive()){
return;
}else{
tl.pause();
tl1
.to(card1,{className:'card1 is-active'})
.to(card2,{className:'card2'},'<')
.to(card3,{className: 'card3'},'<')
.to(num1,{className: 'number1 is-active'},'<')
.to(num2,{className: 'number2'},'<')
.to(num3,{className: 'number3'},'<')
.fromTo(card1,{autoAlpha:0},{autoAlpha:1})
}
})
変数num1に「.number1」を代入しております。
JavaScriptでホバーアクションを実装するには「mouseover」を使います。
過去記事でホバーアクションについては紹介してますので良ければそちらもご覧ください。
JavaScriptでホバーアクションを実装する
ここではifelse文を使用して条件分岐をしていきましょう。
実装しやすいようにここでも文字化していきます。
「tl1」の内容は自動アニメーションのときとさほど変わりませんね。
各要素の「is-active」クラスの付け外しと、autoAlphaを設定しているだけです。
あとはホバーを外した際のアクションを設定します。「mouseleave」ですね。
num1.addEventListener('mouseleave',function(){
tl.restart();
});
tl.restart();とすることで、最初からtlのアニメーションが開始されます。
他にもtl.play();でアニメーションを再開させることもできます。(止めた続きから始まる)
あとは、それぞれの要素のホバーアクションを設定すれば完成ですね!!
最後にもう一度完成品を貼っておきます↓
See the Pen ブログ用 自動アニメーション&ホバー by そす (@Sosgoyo) on CodePen.
まとめ
というわけで今回はGSAPで自動アニメーションとホバーアクションを複合させる実装についてご紹介しました!
他にも方法はあるかもですが、試行錯誤しながら辿り着いた方法ですので是非お試しいただけると幸いです。