⬆︎SVGついてのまとめページ、CSSアニメーションの基本コーナーはこちら。
こんにちは、「ふ」です。
前回の記事⬇︎では、<h2>などの見出しをSVGで装飾し、アニメーションさせました。
SVGで巻物アニメーション。
テキスト要素をSVGで装飾。
こういった見出しテキストのアニメーションを、ユーザのスクロールに合わせて発生するように実装してみましょう。ページ内の見出しは1つとは限りませんので、当然複数の要素に対しても対応させていきます。
内容が複雑になり過ぎないよう、今回は簡単なCSSアニメーションを使って進めていくことにしました。
このページのタイトル部分にあるような、ユーザのスクロールに対して<h2>の見出し領域が、
・画面に入ったら左から要素が登場
・画面から出そうになったら左へ消えていく
というものを作っていきます。
この仕組みを使えば、前に紹介した巻物アニメーションに取り入れるのはもちろんのこと、さまざまなCSSプロパティを「ユーザのスクロールに合わせて変化させる」ことができます。
学習して色々とアレンジしてみてください。
それではベースとなる要素を、HTMLとCSSで書いていきましょう。
.space { height:80%; background-color:cadetblue; } .midasi { background-color:beige; padding:1em; }
見出しとして<h2>要素を2つ、距離をとるための余白「.space」を配置しました。
「.space」をおいたのはサンプル用で、実際のwebページで実装する際には必要ありません。
その上で見出し要素についてはtransform:translateXを使い、画面の左外に動かしておきます。
.midasi { background-color:beige; padding:1em; 「「1transform:translateX(-100%);」」 }
見出しが画面の外に隠れました。
初期状態のコーディングはこれでOKです。
見出しが画面に入ったとき、そして画面から出ていきそうなときのアニメーションをCSSに付け加えます。
.deru { animation:deru 1s 「「1forwards」」; } @keyframes deru { to { transform:translateX(0%); } }
見出しが左から入ってくるアニメーションです。
キーフレームについてですが、先ほど見出し要素はtranslateXで画面の左外に追いやりました。そのためto(終了時の状態)をtranslateX(0%)とすれば左外から定位置に戻ってくるようになります。
animation関数に「forwards」を指定するのを忘れないようにしてください。
これはCSSアニメーションが完了後、「終了時の状態を保持する」という指定です。これがないと、出てきた見出し要素がアニメーション完了後、直ちに左外に消えてしまって「見出し」の意味をなさなくなってしまいます💧
.modoru { animation:modoru 1s 「「1forwards」」; } @keyframes modoru { from { transform:translateX(0%); } }
もう1つは要素が画面から出そうなときのアニメーションclass「.modoru」です。
開始時の状態をtranslateX(0%)、つまり定位置の状態にしておけば、アニメーションが進行するにしたがって要素は左外へと消えていきます。
これら2つのclassは現在、どの要素にも指定していません。
次に実装するIntersectionObserverを使って、見出しが画面に入る/出るタイミングでclassを付け加えてアニメーションさせます。
それではJavaScriptのIntersectionObserverを使い、スクロールにアニメーションが対応するよう実装していきます。
「「3//すべての見出しを取得」」「「1 ..@1@」」 const midasis = document.querySelectorAll(".midasi"); 「「3//ルートの上下を少し狭くする」」「「1 ..@2@」」 let options = { bbrootMargin:"-15% 0% -15% 0%" bb}; 「「3//IntersectionObserverを生成」」「「1 ..@3@」」 const observer = new IntersectionObserver(callback,options); 「「3//すべての見出しを監視対象に」」「「1 ..@4@」」 midasis.forEach(function(value) { bbobserver.observe(value); bb}); 「「3//コールバック関数」」「「1 ..@5@」」 function callback(entries) { bb「「3//交差フラグが立ったすべての要素に」」「「1 ..@6@」」 bbentries.forEach(function(value) { bbbb「「3//画面に入るときと出るときを場合分け」」「「1 ..@7@」」 bbbbif(value.isIntersecting) { bbbbbb「「3//classの追加と削除」」「「1 ..@8@」」 bbbbbbvalue.target.classList.remove("modoru"); bbbbbbvalue.target.classList.add("deru"); bbbbbb} else { bbbbbbvalue.target.classList.remove("deru"); bbbbbbvalue.target.classList.add("modoru"); bbbbbb} bb}); }
@1@ midasiクラスのすべての要素を取得。
@2@ このあと記述するIntersectionObserverのオプションです。
Observerの監視範囲の初期値は「上下左右0%」、つまり画面いっぱいに広がっています。そうすると「.modoru」のアニメーションは要素が画面外に出たときに初めて発動することとなり、ユーザに見せることができなくなってしまいます。
そのためrootMarginプロパティで、監視範囲の上下を15%ずつ狭くしておきました。
@3@ IntersectionObserverのインスタンスを生成。
@4@ forEachメソッドを使うことで、すべての見出し要素を監視対象に指定します。
@5@ 交差判定が発生したときに呼び出されるコールバック関数です。
@6@ 交差判定が発生するのは1つの要素だけとは限りません。
たとえば「#midasi1」が画面から出るのと同時に「#midasi2」が画面に入ってくる、などということも考えられます。そのため交差フラグが立ったときに対象となる要素のすべてに処理を施せるよう、ここでもforEachメソッドの中に関数を記述しています。
@7@ 要素が画面に入るとき/出るときでアニメーションの種類を使い分けるため、条件分岐します。
isIntersectingは、observerの監視範囲に要素が入っているかどうかの真偽値を返します。
@8@ 要素に対して不要なclassを削除、必要なclassを追加しています。
現在引数valueにはentries(交差情報)が入っているので、value.targetで要素本体を参照しましょう。
完成です。上下にスクロールしてみてください⬆︎。
画面に入ったり出そうになったりするに反応して、それぞれの見出しが出てきたり引っ込んだりします。
細かなタイミングなどを調整して、お好みのものに仕上げてください ♪
最後までお読みくださり、ありがとうございました。
IntersectionObserverを使ったCSSアニメーションの発火については以前の記事でも取り上げていたのですが、そのときは「要素が画面に入ったとき」だけのアニメーション実装でした。
今回はそれに加え「要素が画面から出そうなとき」のアニメーションも実装したことで、より動き豊かなものができたかと思います。こういった「脇役部分のアニメーション」を加えることで、完成度を上げることができるんですね。
皆さんの作ったCSS/SVGアニメーションにも、この動きを取り入れてみてください。
ではまた〜 ♪
JavaScriptのforEachとは? 〜配列のループメソッドについて。
2022.03.24
HTML要素の一括編集にも。
CSS+JavaScript、スクロールに合わせて要素をふわっと浮かばせる。
2022.03.01
複数や時間差にも対応。
IntersectionObserverを使いこなす(理解編)。
2022.01.30
「動いているだけのアニメーション」の先へと進もう。
IntersectionObserver、複数の要素や発生位置に対応する(実践編)。
2022.02.06
スクロールに応じたアニメーションを実践。
swift、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。