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

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

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

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

Q&A

解決済

1回答

146閲覧

マウスアウト時の処理開始時間を遅らせる方法

enjoyannna

総合スコア5

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

0グッド

1クリップ

投稿2024/04/25 00:51

実現したいこと

マウスオーバーでアニメーションを開始し、マウスアウトのn秒後(仮に5秒とする)にアニメーションが終了するような処理を行いたい。

発生している問題・分からないこと

①ボタンAにマウスオーバーすると要素Bに対してホバーアニメーションが動作する
②ホバーアニメーションはa~cの3パターン用意、マウスーバーを行うたびにa⇒b⇒cと順番に切り替わる

上記①②の処理を作成し、現状ではボタンAからマウスアウトするとすぐにアニメーションが終了する仕様になっています。

こちらを、マウスアウトしてもしばらくアニメーションが続くように変更したいです。
また、【マウスオーバーしてアニメーションaが開始】⇒【マウスアウトしてもアニメーションaが継続】⇒【再びマウスオーバーしたら仮にアニメーションaの動作時間が残っていてもアニメーションbに切り替え】というように、マウスオーバーを起点として強制的に次のアニメーションが開始するようにしたいと考えています。

transition-delayで実現できるかどうかダメ元で試してみましたが上手くいきませんでした。

また、javascriptのsetTimeoutを用いて実現できそうだと考えましたが、どこにどのようにコードを記載すれば動作するのかが全くわかりません。
②の処理でjavascriptを用いていますが、以前別の質問をした際に回答してくださった方の参考データをほぼそのまま使用させて頂いており、自身はまだ勉強中でjavascriptに関してほぼ知識がないため初歩的な質問でしたら申し訳ありません。

該当のソースコード

<div id="target">要素B</div> <div id="btn">ボタンA</div>
/*ボタンA*/ #btn{ width:20%; aspect-ratio: 1 / 1; background-image:url(ボタンA.png); background-size:100%; justify-content:center; align-items:center; } /*要素Bのホバーアニメーションa~c*/ .anime_a{ background-image:url(back_a.png); background-repeat: no-repeat; background-size: 100%; } .anime_b{ animation:blink_b 0.2s infinite; background-image:url(back_b.png); background-repeat: no-repeat; background-size: 100%; } .anime_c{ animation:blink_c 2s infinite; background-image:url(back_c.png); background-repeat: no-repeat; background-size: 100%; } @keyframes blink_b{ 0%{opacity: 1;} 25%{opacity: 0;} 50%{opacity: 1;} 75%{opacity: 0;} 100%{opacity: 1;} } @keyframes blink_c{ 0%{opacity: 1;} 50%{opacity: 0;} 100%{opacity: 1;} }
//ホバーごとにアニメーションa~cの切り替え document.addEventListener('mouseover', e=>{ const prev=target.dataset.prev??"anime_c"; if(e.target.matches('#btn') ){ if(prev=="anime_c") target.classList.add('anime_a'); if(prev=="anime_a") target.classList.add('anime_b'); if(prev=="anime_b") target.classList.add('anime_c'); } }); document.addEventListener('mouseout', e=>{ if(e.target.matches('#btn')){ if(target.matches('.anime_a')) target.dataset.prev="anime_a"; if(target.matches('.anime_b')) target.dataset.prev="anime_b"; if(target.matches('.anime_c')) target.dataset.prev="anime_c"; target.classList.remove('anime_a'); target.classList.remove('anime_b'); target.classList.remove('anime_c'); } });

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

思いつく範囲で変更や修正を行いましたが反映されませんでした。

補足

特になし

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

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

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

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

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

guest

回答1

0

ベストアンサー

AbortController を使うとすっきり書けるかもしれません。

js

1let controller = new AbortController(); 2const sleep = (time, signal) =>// abort付きスリープ関数 3 new Promise(resolve => { 4 setTimeout(resolve, time) 5 signal.addEventListener('abort', resolve) 6 }); 7 8//ホバーごとにアニメーションa~cの切り替え 9document.addEventListener('mouseover', async e => { 10 const prev = target.dataset.prev ?? "anime_c"; 11 if (e.target.matches('#btn')) { 12 await controller.abort(); // スリープを強制終了させる 13 if (prev == "anime_c") target.classList.add('anime_a'); 14 if (prev == "anime_a") target.classList.add('anime_b'); 15 if (prev == "anime_b") target.classList.add('anime_c'); 16 } 17}); 18 19document.addEventListener('mouseout', async e => { 20 if (e.target.matches('#btn')) { 21 if (target.matches('.anime_a')) target.dataset.prev = "anime_a"; 22 if (target.matches('.anime_b')) target.dataset.prev = "anime_b"; 23 if (target.matches('.anime_c')) target.dataset.prev = "anime_c"; 24 controller = new AbortController(); 25 await sleep(5000, controller.signal); // スリープ強制終了されなければ 5000ミリ秒待機 26 target.classList.remove('anime_a'); 27 target.classList.remove('anime_b'); 28 target.classList.remove('anime_c'); 29 } 30});

もしかすると、Promise.withResolvers()の方がわかりやすいかもしれないですが、わりと新しめなのでブラウザ対応が厳しいかもしれません。

AbortSignal - Web API | MDN
Promise.withResolvers() - JavaScript | MDN

投稿2024/04/25 02:03

Lhankor_Mhy

総合スコア36134

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

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

enjoyannna

2024/04/25 03:17

希望通りの動作になりました!回答及びコードの提供本当にありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問