質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

2回答

294閲覧

jQueryで、重ねた画像を順番に表示⇄非表示するループ処理を実現したい

chibikurochan

総合スコア5

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

1クリップ

投稿2024/04/09 22:49

編集2024/04/10 15:36

実現したいこと

イメージ説明
①画面を描画したら、すぐにアニメーションの処理を開始。
②最初はmini_window_icon_wrap内の3枚の画像を表示しておき、一番上に重ねている1枚目の画像から2枚目までを順番に非表示にする処理を行う。3枚目にはアニメーションを適用しない。
③上記の非表示処理が終わったとき、3枚目の画像は表示したままの状態が正しい。
④その後、あまり間隔を空けずに、続けて表示の処理を開始し、2枚目の画像→1枚目の画像、の順番で表示の処理を行う。
⑤表示の処理が終わったら、あまり間隔を空けずに、続けて②の処理から繰り返す。

※参考
https://www.pinterest.jp/pin/707135578997418566/sent/?invite_code=0f1f9b9b4be94783aae454df7190032b&sender=477944716613135559&sfo=1

前提

以下セクションをHTML内に3つ(仮に上からA-B-Cとします)用意し、
mini_window_icon_wrap内の3枚の画像のうち、上から2枚の画像にのみアニメーションの処理を適用したい。

HTML

1<section class="hogehoge"> 2 <div class="mini_window_icon_wrap"> 3 <img 4 src="./assets/img/mini_window_icon_1.png" 5 alt="" 6 loading="lazy" 7 /> 8 <img 9 src="./assets/img/mini_window_icon_1.png" 10 alt="" 11 loading="lazy" 12 /> 13 <img 14 src="./assets/img/mini_window_icon_1.png" 15 alt="" 16 loading="lazy" 17 /> 18 </div> 19</section>

SCSS

1.mini_window_icon_wrap { 2 z-index: 9999; 3 position: relative; 4 max-width: 146px; 5 width: 100%; 6 min-height: 107px; 7 height: 100%; 8 margin: -8.53334vw 5.33334vw 2.133334vw auto; 9 10 img { 11 position: absolute; 12 top: 0; 13 left: 0; 14 // opacity: 0; 15 transition: opacity 1s ease-in-out; 16 17 &.active { 18 opacity: 1; 19 } 20 21 &:nth-child(1) { 22 z-index: 9999; 23 } 24 &:nth-child(2) { 25 z-index: 8888; 26 top: 2.66667vw; 27 left: -2.66667vw; 28 } 29 &:nth-child(3) { 30 z-index: 7777; 31 top: 5.33334vw; 32 left: -5.33334vw; 33 } 34 } 35 }

発生している問題・エラーメッセージ

・エラーは発生していないが、期待する挙動になっていない。
・A B Cの各セクションで、挙動が異なっている。

A B C全てで実現できていないこと:
①アニメーションの処理開始にやや時間がかかっている。画面を描画したらできるだけ早く処理を開始したい。
②mini_window_icon_wrap内の3枚の画像を最初から表示しておく処理ができていない。

AとBで実現できていないこと:
②最初は非表示の処理から開始したいが、最初は何も表示されていない状態で、④の表示の処理から開始してしまっており、かつ3枚目の画像にもアニメーションが適用されているため、3枚目→2枚目→1枚目の順番で表示の処理が行われている。
③3枚目の画像にはアニメーションを適用せず常に表示しておく、が正しい挙動だが、適用されてしまっており、かつ②の非表示の処理が終わるとHTMLのimgタグに自動的にstyle="display: none;"が追加され、非表示となってしまっている。

※参考動画
https://capture.dropbox.com/4rAH2Khu6SoOcluI

Cで実現できていないこと:
②最初は非表示の処理から開始したいが、一番下の3枚目のみが最初に表示されていて、④の表示の処理から開始してしまっている。

※参考動画:
https://capture.dropbox.com/ENrKLF1zCzR3yR93

※エラーメッセージなし

該当のソースコード

jQuery

1//ミニウィンドウに対するアニメーションの処理 2$(function () { 3 var images = $('.mini_window_icon_wrap img'); 4 var currentIndex = 0; // 最初は一枚目の画像から開始 5 var animationDirection = 'forward'; // 最初のアニメーション方向は前向き 6 7 function showImage(index) { 8 $(images[index]).addClass('active').show(); 9 } 10 11 function hideImage(index) { 12 $(images[index]).removeClass('active').hide(); 13 } 14 15 function animateImages() { 16 setTimeout(function () { 17 if (animationDirection === 'forward') { 18 if (currentIndex < images.length - 1) { 19 hideImage(currentIndex); 20 currentIndex++; 21 animateImages(); 22 } else { 23 animationDirection = 'backward'; // アニメーション方向を逆に変更 24 currentIndex = images.length - 2; // インデックスを初期化(最後から2枚目の画像から開始) 25 setTimeout(hideImageStep, 150); // 0.15秒後に非表示の段階的な処理を開始 26 } 27 } else { 28 if (currentIndex >= 0) { 29 showImage(currentIndex); 30 currentIndex--; 31 animateImages(); 32 } else { 33 animationDirection = 'forward'; // アニメーション方向を逆に変更 34 currentIndex = 1; // インデックスを初期化 35 setTimeout(showImageStep, 150); // 0.15秒後に表示の段階的な処理を開始 36 } 37 } 38 }, 300); // 0.3秒ごとにアニメーションを繰り返す 39 } 40 41 function hideImageStep() { 42 if (currentIndex >= 0) { 43 hideImage(currentIndex); 44 currentIndex--; 45 if (currentIndex >= 0) { 46 setTimeout(hideImageStep, 150); // 0.15秒後に次の画像を非表示にする 47 } else { 48 currentIndex = images.length - 1; 49 animateImages(); 50 } 51 } 52 } 53 54 function showImageStep() { 55 if (currentIndex < images.length) { 56 showImage(currentIndex); 57 currentIndex++; 58 if (currentIndex < images.length - 1) { 59 setTimeout(showImageStep, 150); // 0.15秒後に次の画像を表示する 60 } else { 61 currentIndex = 0; 62 setTimeout(animateImages, 150); // 0.15秒後にアニメーションを再開する 63 } 64 } 65 } 66 67 // 最初に表示しておく 68 images.each(function (index) { 69 if (index >= 1 && index < images.length - 1) { 70 hideImage(index); 71 } 72 }); 73 showImage(images.length - 1); // 最後の画像を表示しておく 74 setTimeout(animateImages, 0); // 画面描画後すぐにアニメーションの処理を開始 75});

試したこと

1)各セクションごとに挙動が異なるため、jsの記述の最後に以下のような記述を追加して、各セクションに対してアニメーションが適用されるように試した。
→解決できなかったどころか、アニメーションが動かなくなった。

// Aセクション animateMiniWindow($('#A .mini_window_icon_wrap img')); // Bセクション animateMiniWindow($('#B .mini_window_icon_wrap img')); // Cセクション animateMiniWindow($('#C .mini_window_icon_wrap img'));

2)念のため、HTML内のjQueryのとjsの呼び出し位置が問題ないかを確認。
→問題なさそう。headタグ内ではうまく動作しないことが過去にあったため、いつもbody閉じタグの直前に入れています。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <script src="./assets/js/common.js"></script> </body> </html>

2024/4/11時点:
以下のように、最初に各セクションに対しての画像処理を行う記述を追加したところ、A, B, Cの挙動を統一できました!

現時点で実現できていないことは、以下の内容のみになります。
②最初はmini_window_icon_wrap内の3枚の画像を表示しておき、一番上に重ねている1枚目の画像から2枚目までを順番に非表示にする処理を行う。
④その後、あまり間隔を空けずに、続けて表示の処理を開始し、2枚目の画像→1枚目の画像、の順番で表示の処理を行う。

追加したコード

jQuery

1animateImages('.pile_zipup_blouson .mini_window_icon_wrap img'); 2animateImages('.border_tee .mini_window_icon_wrap img'); 3animateImages('.hoodie_sweatshirts .mini_window_icon_wrap img');

修正後のコード全文

jQuery

1//ミニウィンドウに対するアニメーションの処理 2$(function () { 3 // 各セクションの画像処理を開始 4 animateImages('.pile_zipup_blouson .mini_window_icon_wrap img'); 5 animateImages('.border_tee .mini_window_icon_wrap img'); 6 animateImages('.hoodie_sweatshirts .mini_window_icon_wrap img'); 7 8 function animateImages(selector) { 9 var images = $(selector); 10 var currentIndex = 0; 11 var animationDirection = 'forward'; 12 13 function showImage(index) { 14 $(images[index]).addClass('active').show(); 15 } 16 17 function hideImage(index) { 18 $(images[index]).removeClass('active').hide(); 19 } 20 21 function animate() { 22 setTimeout(function () { 23 if (animationDirection === 'forward') { 24 if (currentIndex < images.length - 1) { 25 hideImage(currentIndex); 26 currentIndex++; 27 animate(); 28 } else { 29 animationDirection = 'backward'; 30 currentIndex = images.length - 2; 31 setTimeout(hideImageStep, 150); 32 } 33 } else { 34 if (currentIndex >= 0) { 35 showImage(currentIndex); 36 currentIndex--; 37 animate(); 38 } else { 39 animationDirection = 'forward'; 40 currentIndex = 1; 41 setTimeout(showImageStep, 150); 42 } 43 } 44 }, 300); 45 } 46 47 function hideImageStep() { 48 if (currentIndex >= 0) { 49 hideImage(currentIndex); 50 currentIndex--; 51 if (currentIndex >= 0) { 52 setTimeout(hideImageStep, 150); 53 } else { 54 currentIndex = images.length - 1; 55 animate(); 56 } 57 } 58 } 59 60 function showImageStep() { 61 if (currentIndex < images.length) { 62 showImage(currentIndex); 63 currentIndex++; 64 if (currentIndex < images.length - 1) { 65 setTimeout(showImageStep, 150); 66 } else { 67 currentIndex = 0; 68 setTimeout(animate, 150); 69 } 70 } 71 } 72 73 images.each(function (index) { 74 if (index >= 1 && index < images.length - 1) { 75 hideImage(index); 76 } 77 }); 78 showImage(images.length - 1); 79 setTimeout(animate, 0); 80 } 81});

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2024/04/10 00:32

具体的に何をどうしたいか図示できませんか? 参考として提示されたサイトも特に命題のような内容になっていないと思います
Lhankor_Mhy

2024/04/10 01:41

ご提示のコードを試してみましたが、Aの表示が終わったらBの表示、のようにABCの処理を順番にしているようですが、これは想定通りなのですか? それとも、ABCの処理は独立に行われてほしいのですか?
chibikurochan

2024/04/10 15:37 編集

@yambejpさま 早々にご質問くださりありがとうございます。 「実現したいこと」に図解を追加しました。 ご確認いただけますでしょうか。
chibikurochan

2024/04/10 15:37 編集

@Lhankor_Mhyさま 早々にご質問くださりありがとうございます。 ABCの処理は個別に実行する、が期待している挙動です。
guest

回答2

0

②最初はmini_window_icon_wrap内の3枚の画像を表示しておき、一番上に重ねている1枚目の画像から2枚目までを順番に非表示にする処理を行う。

以下を削除

js

1images.each(function (index) { 2 if (index >= 1 && index < images.length - 1) { 3 hideImage(index); 4 } 5});

④その後、あまり間隔を空けずに、続けて表示の処理を開始し、2枚目の画像→1枚目の画像、の順番で表示の処理を行う。

以下のように変更

js

1if (animationDirection === 'forward') { 2 if (currentIndex < images.length - 1) { 3 hideImage(currentIndex); 4 currentIndex++; 5 animate(); 6 } else { 7 console.log(currentIndex) 8 animationDirection = 'backward'; 9 // currentIndex = images.length - 2; 10 // setTimeout(hideImageStep, 150); 11 animate(); 12 } 13} else { 14 if (currentIndex >= 0) { 15 showImage(currentIndex); 16 currentIndex--; 17 animate(); 18 } else { 19 animationDirection = 'forward'; 20 // currentIndex = 1; 21 // setTimeout(showImageStep, 150); 22 animate(); 23 } 24}

投稿2024/04/11 00:38

Lhankor_Mhy

総合スコア36134

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

  1. 対象の<img>要素を含む配列を作る
  2. 最初の<img>要素を表示、それ以外を非表示する
  3. ループ処理でカウンタを加算する
  4. ループ処理でカウンタと同じインデックスの<img>要素を表示、それ以外を非表示する

参考までに(実運用に合わせて調整はしてください)。

javascript

1const imgs = []; 2let index = 0; 3setInterval(_ => { 4 imgs.forEach((img, i) => { 5 img.style.display = i === index? 'block': 'none'; 6 }); 7 index ++; 8 index %= imgs.length; 9}, 1000)

投稿2024/04/09 23:35

Refrain

総合スコア532

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

chibikurochan

2024/04/10 14:03

@Refrainさま 早々にご回答くださりありがとうございます。 いただいたコードを少し調整して挙動を確認してみましたが、期待する挙動になりませんでした。 結果 https://capture.dropbox.com/uDni8fDVoDBt4aPS 調整後の記述 ========================================== $(function () { const imgs = $('.mini_window_icon_wrap img'); let index = 0; setInterval(() => { imgs.each((i, img) => { $(img).css('display', i === index ? 'block' : 'none'); }); index++; index %= imgs.length; }, 1000); }); ========================================== 以下が期待する挙動ですが、いずれも実現できていません。 ========================================== ①画面を描画したら、すぐにアニメーションの処理を開始。 ②最初はmini_window_icon_wrap内の3枚の画像を表示しておき、一番上に重ねている1枚目の画像から2枚目までを順番に非表示にする処理を行う。3枚目にはアニメーションを適用しない。 ③上記の非表示処理が終わったとき、3枚目の画像は表示したままの状態が正しい。 ④その後、あまり間隔を空けずに、続けて表示の処理を開始し、2枚目の画像→1枚目の画像、の順番で表示の処理を行う。 ⑤表示の処理が終わったら、あまり間隔を空けずに、続けて②の処理から繰り返す。 ==========================================
Refrain

2024/04/10 14:51

手元で同じ環境が揃えられないので`<div>`で代用しますが、以下のようなイメージでしょうか? ```javascript // 取り敢えず10個<div>作成 let div; for (let i = 0; i < 10; i ++) { div = document.createElement('div'); div.style.backgroundColor = 'red'; div.style.border = 'solid 1px black'; div.style.height = '300px'; div.style.left = `${i * 10}px`; div.style.position = 'absolute'; div.style.top = `${i * 10}px`; div.style.width = '400px'; document.body.appendChild(div); } // <div>の一覧 const divs = document.querySelectorAll('div'); // カウンタ変数cと変位量d let counter = 0, delta = 1; setInterval(_ => { // 全部の<div>表示 divs.forEach((div, i) => { div.style.display = (divs.length - i) > counter? 'block': 'none'; }); // 任意の範囲の<div>非表示 // for (let i = 0; i < counter; i ++) // divs[divs.length - i - 1].style.display = 'none'; // カウンタ変数の計算 counter += delta; // 折り返し地点に付いたら変位量を反転させる if (counter === divs.length - 1 || counter === 0) delta *= -1; }, 1000); ```
chibikurochan

2024/04/10 15:05

回答ありがとうございます。 結論、イメージが異なります。 divの表示・非表示を繰り返し処理するのではなく、mini_window_icon_wrapクラスが付いたdivの中にあるimgタグの表示・非表示を繰り返す、が正しいです。 jsで要素の追加やスタイルを上書きしないとうまく挙動しない場合は例外としますが、 保守性を考慮して、基本的には、要素はhtml内にdivとimgを記述し、スタイルはscssファイル内に記述したいので、jsでのhtmlタグとスタイルの付与は考えていません。 jsには挙動の部分のみ記述したいです。
chibikurochan

2024/04/10 15:07

<section class="hogehoge"> <div class="mini_window_icon_wrap"> <img src="./assets/img/mini_window_icon_1.png" alt="" loading="lazy" /> <img src="./assets/img/mini_window_icon_1.png" alt="" loading="lazy" /> <img src="./assets/img/mini_window_icon_1.png" alt="" loading="lazy" /> </div> </section> 説明にも記載していますが、htmlには実際上記の記述が3つ存在していて、各セクションのmini_window_icon_wrapクラスが付いたdivタグ内の画像に対して同じ処理を行いたいです。
Refrain

2024/04/10 22:49

いえ、こちらの環境では`<img>`周りが全て用意出来なかったので、代替で`<div>`を使っています。 ご使用環境の目的のセレクターを使用しての`divs`に相当する要素を取得し、コードの改変を実施してください。 また、CSSを分離させたい場合には、`style`属性の操作ではなく`className`の操作などを実施し、`CSS`側で`display`などを定義すると良いかもしれません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問