質問: true) { return false; } else { animation(); } }); ``` ### 試したこと 「.fade-in が付与されたら、その要素だけは監視を終了する」 という解釈になると思うのですが、具体的な方法に検討がつきません。 考えた挙句に上記の「#js-stop(最後の画像)に .fade-in が付与されたら終了する」という処理になりました。 以上が質問です。 よろしくお願いいたします。
回答: 一連の動作の説明は実装するのに必要十分です。この説明のとおりに実際にコーディングに落とし込むには少しだけテクニックが必要です。 知っておくと便利な方法として、JavaScriptにおいて「HTMLの要素の参照使い回す」ことです。 どういうことかというと、`document.getElementById`や`document.querySelector`などで取得できるHTMLの要素の参照を変数上で保持し続け、これに対して値の取得や変更を行うことでJavaScript中のHTMLの表現方法が柔軟になります(※)。 実際に書いて動いたものを以下に載せます。 ``` // 一度だけ`.fade`を格納する const fadeElements = $(".fade"); // すでに`.fade-in`が追加された要素の参照を格納する配列 const fadeInEndElements = []; // `.fade`の個数 const fadeInCount = fadeElements.length; function animation() { // すべての`.fade`要素に対して`.fade-in`のclassNameが追加された場合 if (fadeInEndElements.length === fadeInCount) { // すべての要素に対して`.fade-in`が追加されたので、登録していたイベントを解除する $(window).off("scroll", animation); // すべて完了している場合はこれ以上の処理を実行しない return; } fadeElements.each(function() { // `.fade-in`が付いていない要素かどうか確認する if (fadeInEndElements.includes(this)) { // すでに`.fade-in`が付いている場合はこれ以上の処理をしない // ここが発生している問題の解決ポイントです return; } const target = $(this).offset().top; const scroll = $(window).scrollTop() - 200; const windowHeight = $(window).height(); if (scroll > target - windowHeight) { // .fade-in を追加 $(this).addClass("fade-in"); // .fade-in が追加された要素の参照(this)を格納する fadeInEndElements.push(this); } }); } // スクロールイベントに対して、animationのイベント関数を登録する $(window).scroll(animation); ``` `fadeInEndElements.push(this);`と書いている部分が今回の肝となる部分なのでじっくりと確認してみてください。 ※ ただし、この方法にはHTML要素が他者から変更された場合に参照がなくなるという問題がありますが、おそらくこの様な場面に遭遇するときには、実装力をより上げなければならない状況だと思います。今回の質問の範囲ではおそらく無いと考えられますので、無視していただいて結構です。