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

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

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

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

jQuery

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

Q&A

解決済

3回答

504閲覧

JavaScriptの「transitionend」をキャンセルできないでしょうか?

nikuatsu

総合スコア177

JavaScript

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

jQuery

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

2グッド

3クリップ

投稿2022/09/25 16:12

編集2022/09/25 16:22

実現したいこと

JavaScriptのtransitionendをキャンセルできないでしょうか?

発生している問題

ifの中を通っていないのに、ifの中のtransitionendの処理が走ってしまいます。

該当のソースコード

次のソースコードはchangeBox()をこのように2回処理をしています。

1回目
changeBox()typenull を渡す
.boxtransitionend をかけ、p.text( 'いいい' ); にする

2回目
changeBox()type'show' を渡す
p.text( 'あああ' ); にする

なのに2回目に'いいい'になってしまうのです。

https://jsfiddle.net/omLy95bq/

html

1<p>●●●</p> 2<div class="box">box</div>

css

1.box { 2 transition: 1s; 3 background: gray; 4} 5.box.is_red { 6 background: pink; 7} 8.box.is_blue { 9 background: skyblue; 10}

JavaScript

1$(function(){ 2 3 changeBox( null ); // 1回目 4 changeBox( 'show' ); // 2回目 5 6 function changeBox( type ) { 7 8 if ( type == 'show' || type === 'up' || type === 'down' ) { 9 $( 'p' ).text( 'あああ' ); 10 } 11 12 $( '.box' ).addClass( type === null ? 'is_red' : 'is_blue' ); 13 14 if ( type === null ) { 15 $( '.box' ).on('transitionend', function() { 16 $( 'p' ).text( 'いいい' ); 17 }); 18 } 19 20 } 21 22});

試したこと

試したこと➀:時間差の確認

'いいい'にしたいのはnullを渡した場合だけなのに、なぜこうなってしまうのか?

まず考えたのはtransition: 1s;の途中で2回目を実行しているせいか?という疑念で、その確認のために2回目をsetTimeoutで実行しました。しかし変化なく、相変わらず2回目に'いいい'になってしまいます。

https://jsfiddle.net/omLy95bq/1/

JavaScript

1$(function(){ 2 3 changeBox( null ); // 1回目 4 // changeBox( 'show' ); // 2回目 5 setTimeout( ()=>{ changeBox( 'show' ); }, 5000 ); // 2回目 6 7 /* 8 省略 9 */ 10 11});
試したこと②:コンソールの確認

次に各所でコンソールを確認してみました。

1回目は'nullが渡されました''いいいにします'が出力されるのですが、
2回目は'あああにします''いいいにします'が出力されます。

つまり2回目はifの中('nullが渡されました')を通っているわけではなく、しかしifの中のtransitionendの中('いいいにします')を通っているように見受けられました。

https://jsfiddle.net/omLy95bq/2/

JavaScript

1$(function(){ 2 3 changeBox( null ); // 1回目 4 // changeBox( 'show' ); // 2回目 5 setTimeout( ()=>{ changeBox( 'show' ); }, 5000 ); // 2回目 6 7 function changeBox( type ) { 8 9 if ( type == 'show' || type === 'up' || type === 'down' ) { 10 console.log('あああにします'); 11 $( 'p' ).text( 'あああ' ); 12 } 13 14 $( '.box' ).addClass( type === null ? 'is_red' : 'is_blue' ); 15 16 if ( type === null ) { 17 console.log('nullが渡されました'); 18 $( '.box' ).on('transitionend', function() { 19 console.log('いいいにします'); 20 $( 'p' ).text( 'いいい' ); 21 }); 22 } 23 24 } 25 26});

以上のことから、1回目でtransitionendの処理がどこかに登録(?)されたまま、2回目の実行ではその登録は解除されず、処理が走ってしまうという状況のように思われます。

そこでタイトルの質問になります。

「transitionend」をキャンセルできないでしょうか?

具体的にイメージしているのは次のようなキャンセルで、これなら2回目に 'show' を渡した時点で、1回目に登録された処理は走らないだろうという目論見です。

JavaScript

1 if ( type == 'show' || type === 'up' || type === 'down' ) { 2 $( '.box' ).on('cancelTransitionend'); // 「transitionend」をキャンセル 3 $( 'p' ).text( 'あああ' ); 4 }

バージョン

jQuery 3.6.0

補足

尚、MDNを見るとtransitioncancelというそれっぽい名前の関数があったのですが、これは登録されているtransitionendをキャンセルするのではなく、CSSのtransitionが途中でキャンセルされたときに発火させたいイベントを登録する関数のようです。

kemusi, Cocode👍を押しています

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

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

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

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

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

guest

回答3

0

ベストアンサー

質問にある jsfiddle

https://jsfiddle.net/omLy95bq/

に書かれているコードの if (type === null) に対する else として以下を追加するとどうでしょう?

diff

1 if (type === null) { 2 $('.box').on('transitionend', function() { 3 $('p').text('いいい'); 4 }); 5- } 6+ } else { 7+ $('.box').off('transitionend'); 8+ } 9

この修正は、transitionendイベントを発生しないようにするというものではなく、type===null のときに設定したtransitionend発生時のコールバックをその直後のtype==='show' のときに解除するという修正です。これによって1秒後に実際にtransitionendが発生したときにはコールバックが設定されていないので何も起こらず、その結果 <p> のテキストが いいい にならなくなるかと思います。

投稿2022/09/25 19:37

編集2022/09/25 19:38
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Cocode

2022/09/25 20:06

部外者ですが…すっごいいい回答ですね!!1回目に呼び出したtransitionedがずっと有効中だから、transitionが起こるたびに「いいい」になってしまう。だから、2回目のときに無効化してるのですね。勉強になりました。
nikuatsu

2022/09/26 11:48

ありがとうございます。 .on('cancelTransitionend'); ではなくて .off('transitionend'); というのがあったのですね。
guest

0

一度登録したイベントリスナはイベントが起きる毎に何回でも呼ばれるのがデフォルトの動作なので、何回も呼ばれないように登録を解除する必要があります。jQuery の場合は、on() の代わりに one() で簡単に行うことができます。

js

1 $( '.box' ).one('transitionend', function() {

投稿2022/09/25 21:58

編集2022/09/25 21:59
int32_t

総合スコア20845

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

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

Cocode

2022/09/25 22:35 編集

それ私も試してみたんですけど、1回目が「いいい」になる前に、2回目の処理が終わるので、遅れて1回目の「いいい」がやっと処理終了して、結果「いいい」となってしまいました。 .one() を使用する場合、1回目の処理が全て終了してから2回目の実行を開始しなければならず、cssのtransitionと同じ秒数遅らせて2回目が実行開始されるように .setTimeout() でする必要があります。
nikuatsu

2022/09/26 11:50

ありがとうございます。oneというイベント登録方法もあったとは勉強になりました。
guest

0

勘違いされていると思います。
1回目の changeBox 呼び出し時の on('transitionend', func..) 内の処理は、ご指定の通りtransition 完了後(この場合一秒後)に走ります。※ですのでこの1回目の処理は継続中です。
この時、まだ いいい にはなっておりません。
その間、2回目の changeBox が走ります。
この時、 あああ となります。
この後、transitionが完了するので いいい となります。
transition の完了後に何かを実現したいのか、1回目の処理が完了した後に(コールバックやらを利用し)2回目を走らせたいのかこの辺りのイメージをよく考えてから実装された方が良いと思われます。

投稿2022/09/26 07:18

Yousuck

総合スコア349

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問