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

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

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

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

jQuery

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

HTML

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

CSS

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

Q&A

解決済

1回答

1259閲覧

ハンバーガーメニューの開閉が2回目から同時に発生してしまう。

ysmd

総合スコア17

JavaScript

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

jQuery

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

HTML

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

CSS

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

0グッド

0クリップ

投稿2021/04/15 09:20

ハンバーガーメニューの挙動は1回目は正常に開閉できるのですが、
2回目からは開閉イベントが同時に発生するという現象に苦戦しています。

クリックした時に、一瞬表示されてすぐに非表示になります。
その際本来ならメニュークリックのタイミングでヘッダーが非表示になるはずが残り続けるという問題もあります。

当初はハンバーガーメニューをヘッダーに、閉じるボタンはクリック後表示されるメニュー内に配置して、
2つのボタンで制御していました。
それをヘッダーのハンバーガーメニューのみで制御することに変更をしたことで、
開閉のイベントが同時に発生するようになったと考えられます。

表示用と非表示用のkeyframeを2つ作りアニメーションさせています。
クリックでclassの付け替えをして表示非表示をさせる処理にしています。
addClassやremoveClassをtoggleClassに変更して制御を試みましたが、解決には至りませんでした。

今のコードの書き方は、開く処理、閉じる処理をそれぞれ記述しています。
開く処理と閉じる処理のクリック判定に同一クラスを設定しているため同時にイベントが発火しているかと思います。

アドバイスのほど何卒よろしくお願いいたします。

 
こちら挙動のイメージ画像です。
イメージ説明
イメージ説明
イメージ説明

gifのイメージになります。
カクカクして見にくいかもしれません・・・
イメージ説明

jQuery

1 const $body = $('body') 2 const $navButton = $('.global-hamburger') 3 const $globalNav = $('#globalNav') 4 const $globalMenu = $('#globalMenu') 5 const $closeBtn = $('.global-hamburger') 6 const $subMenu = $globalNav.find('.sub-menu') 7 const $snsMenu = $globalNav.find('.sns-menu') 8 9 const CLASS_ACTIVE = 'active' 10 const CLASS_MOVE = 'move' 11 const CLASS_REMOVE = 'remove' 12 const CLASS_SHOW = 'show' 13 const CLASS_SLIDE_R = 'slide-r' 14 const CLASS_PREVENT = 'scroll-prevent' 15 16 $navButton.on('click', (e) => { 17 $globalNav.show(0, () => { 18 $navButton.toggleClass(CLASS_ACTIVE) 19    $('.header-logo').css('display','none'); 20 $('.header-nav').css('display','none'); 21 $('.dot').css('background-color','#fff'); 22 23 $globalNav.addClass(CLASS_MOVE) 24 25 $('.move #boxT4').on('animationend', () => { 26 $globalMenu.addClass(CLASS_SHOW) 27 28 $globalMenu.find('li > a').on('animationend', () => { 29 for (let i = 0; i < $subMenu.length; i++) { 30 $subMenu[i].classList.add(CLASS_SLIDE_R) 31 } 32 $snsMenu.addClass(CLASS_SLIDE_R) 33 $body.addClass(CLASS_PREVENT) 34 $globalNav.css('background-color', '#3b3b45') 35 }) 36 }) 37 }) 38 if ($globalNav.hasClass(CLASS_MOVE)) { 39 $navButton.on('click', () => { 40 $('.header-logo').css('display','block'); 41 $('.header-nav').css('display','block'); 42 $globalNav.css('background-color', 'transparent') 43 $body.removeClass(CLASS_PREVENT) 44 $globalNav.removeClass(CLASS_MOVE) 45 $globalNav.addClass(CLASS_REMOVE) 46 for (let i = 0; i < $subMenu.length; i++) { 47 $subMenu[i].classList.remove(CLASS_SLIDE_R) 48 } 49 $snsMenu.removeClass(CLASS_SLIDE_R) 50 $globalMenu.removeClass(CLASS_SHOW) 51 52 $globalNav.on('animationend', () => { 53 if ($globalNav.hasClass(CLASS_REMOVE)) { 54 $globalNav.hide(0, () => { 55 $globalNav.removeClass(CLASS_REMOVE) 56 }) 57 } 58 }) 59 }) 60 } 61 }) 62 63 $globalMenu.find('a[href]').on('click', () => { 64 $navButton.trigger('click') 65 })

html

1<nav id="globalNav" class="global-nav"> 2 <div class="global-nav__inner"> 3 <div id="boxT1" class="slide-box slide-box--t1"></div> 4 <div id="boxT2" class="slide-box slide-box--t2"></div> 5 <div id="boxT3" class="slide-box slide-box--t3"></div> 6 <div id="boxT4" class="slide-box slide-box--t4"></div> 7 <div id="globalMenu" class="global-menu-wrapper"> 8 <?php 9 wp_nav_menu(array( 10 'theme_location' => 'global-menu', 11 'menu_class' => 'global-menu' 12 )); 13 ?> 14 <div class="global-links"> 15 <p class="contact-link"><a href="<?php echo home_url('/contact') ?>">お問い合わせ</a></p> 16 <?php get_template_part('/template/common/sns-list'); ?> 17 </div> 18 </div> 19 </div> 20 </nav> 21 <header> 22 <div class="header__column"> 23 <div> 24 <?php getCustomLogo() ?> 25 </div> 26 <div class="column__flex"> 27 <div class="header-nav-box"> 28 <nav class="header-nav"> 29 <?php 30 wp_nav_menu(array( 31 'theme_location' => 'header-menu', 32 'menu_class' => 'header-menu' 33 )); 34 ?> 35 </nav> 36 </div> 37 <div class="global-hamburger-box"> 38 <div class="global-hamburger"> 39 <button id="navButton"> 40 <span class="dot dot--top"></span> 41 <span class="dot dot--bottom"></span> 42 </button> 43 </div> 44 </div> 45 </div> 46 </div> 47 </header>

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

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

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

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

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

Lhankor_Mhy

2021/04/15 09:33

animationend イベントを拾っているように見えるのですが、CSSなしでもこれは動くのですか?
ysmd

2021/04/15 09:42

こちらcssがないと動きません。 アニメーション終了後、keyframeなどのcssを付加させて 別アニメーションが発生するようにしています。
Lhankor_Mhy

2021/04/15 10:33

とすると、回答者がテストできないと思いますが…… 具体的なコードがないと、推測によるふんわりした回答になりますが、かまいませんか?
ysmd

2021/04/15 12:07

必要なcssを貼ろうとしましたが文字数の制限により腫れませんでした・・・ テストできない状態で申し訳ありませんが、推測での回答をいただけますと幸いです。
ysmd

2021/04/15 12:10 編集

本文では文字数制限で貼り付けられませんでしたが、headerとハンバーガーメニューに関するcssの箇所をこちらに記載します。 $color-white: #fff; $color-gmenu: #3b3b45; $pc: 1025px; $tab: 600px; $spSide: landscape; $sp: 599px; @mixin pc { @media (min-width: ($pc)) { @content; } } @mixin tab { @media (min-width: ($tab)) { @content; } } @mixin sp { @media (max-width: ($sp)) { @content; } } @mixin spSide { @media (orientation: ($spSide)) { @content; } } @mixin fz($size: 16) { font-size: ($size / 10) + rem; } html { font-size: 62.5%; } body.scroll-prevent { overflow: hidden; height: 100%; } .bg-is-black .dot { background-color: #fff; } // header header { z-index: 50; position: fixed; top: 0; width: 100%; padding: 20px; animation: addPadding 0.5s forwards; &.header_padding { animation: removePadding 0.5s forwards; } @keyframes removePadding { 0% { padding: 20px; } 100% { padding: 0; } } @keyframes addPadding { 0% { padding: 0; } 100% { padding: 20px; } } .header__column { position: relative; display: flex; justify-content: space-between; align-items: flex-start; transition: all 0.8s; > div { &.column__flex { display: flex; align-items: center; justify-content: space-between; .header-nav-box { animation: navTop 0.5s forwards; } .header_navi-none { .header-nav { display: none; } } } } } .header-logo { width: 80px; height: 80px; padding: 12px 16px 12px 14px; box-sizing: border-box; background: #1d2089; animation: normalsize 0.5s forwards; &.shrink { animation: smaller 0.5s forwards; margin: -12px; @include tab { margin: 0; } } @keyframes smaller { 0% { transform: scale(1); } 100% { transform: scale(0.7); } } @keyframes normalsize { 0% { transform: scale(0.7); } 100% { transform: scale(1); } } @include tab { padding: 35px 40px; @keyframes smaller { 0% { width: 140px; height: 140px; } 100% { width: 70px; height: 70px; padding: 8px 10px; } } @keyframes normalsize { 0% { width: 70px; height: 70px; padding: 8px 10px; } 100% { width: 140px; height: 140px; } } } img { width: 95%; height: 100%; } } .header_logo-none { display: none; } .header-nav { display: none; @include pc { display: block; } } .header-menu { z-index: 30; display: flex; align-items: center; margin-right: 1rem; > li { margin-right: 4rem; > a { font-size: 12px; line-height: 1.8; &:hover { text-decoration: underline; } } &:last-child { margin-right: 0; } } } } .global-hamburger-box { .global-hamburger,.global-hamburger-close { display: block; width: 80px; height: 80px; position: relative; animation: normalburger 0.5s forwards; #navButton { position: absolute; top: 10%; left: 50%; transform: translate(-50%,-50%); @include pc { top: 50%; } } &.smallburger { animation: smallburger 0.5s forwards; margin-top: 10px; @include pc { margin: 0; } } @include pc { @keyframes smallburger { 0% { width: 170px; height: 100px; } 100% { width: 70px; height: 70px; } } @keyframes normalburger { 0% { width: 70px; height: 70px; } 100% { width: 170px; height: 100px; } } } .dot { position: absolute; top: 50%; left: 50%; transform: translateY(-50%) translateX(-50%); width: 30px; height: 1px; // background: #222; &.dot--top { top: calc(50% - 5px); transition: .3s; } &.dot--bottom { top: calc(50% + 5px); transition: .3s; } } } .active { .dot { &.dot--top { top: 0px; left: -15px; transform: rotate(135deg); transition: .3s; } &.dot--bottom { top: 0px; left: -15px; transform: rotate(45deg); transition: .3s; } } } } .global-nav { z-index: 50; position: fixed; top: 0; left: 0; right: 0; bottom: 0; width: 100%; height: 100%; display: none; overflow-y: scroll; .global-nav__inner { position: relative; width: 100%; height: 100%; } .slide-box { width: 100%; height: 25vh; background-color: $color-gmenu; } .slide-box--t4 { height: 100vh; @include tab { height: 25vh; } } &.move { display: block; @keyframes moveBox { 0% { transform: translateX(100%); } 100% { transform: translateX(0); } } #boxT1 { animation: moveBox 0.4s ease-in forwards; position: fixed; top: 0; } #boxT2 { animation: moveBox 0.5s ease-in forwards; position: fixed; top: 25vh; } #boxT3 { animation: moveBox 0.6s ease-in forwards; position: fixed; top: 50vh; } #boxT4 { animation: moveBox 0.7s ease-in forwards; position: fixed; top: 75vh; } @keyframes slideIn { 0% { opacity: 0; top: 0; right: 0; } 100% { opacity: 1; top: 50px; right: 50px; } } .cross-icon { z-index: 90; position: fixed; animation: slideIn .5s forwards; } } &.remove { @keyframes removeBox { 0% { transform: translate(0); } 100% { transform: translateX(150%); } } #boxT1 { animation: removeBox 1.2s ease forwards; position: fixed; top: 0; } #boxT2 { animation: removeBox 1s ease forwards; position: fixed; top: 25vh; } #boxT3 { animation: removeBox 0.8s ease forwards; position: fixed; top: 50vh; } #boxT4 { animation: removeBox 0.6s ease forwards; position: fixed; top: 75vh; } @keyframes slideOut { 0% { opacity: 1; top: 50px; right: 50px; } 100% { opacity: 0; top: 0; right: 0; } } .cross-icon { z-index: 90; position: fixed; animation: slideOut .5s forwards; } } } .global-menu-wrapper { position: absolute; top: 80px; left: 25%; transform: translateX(-25%); width: 60%; @include spSide { top: 80px; left: 50%; transform: translateX(-50%); width: 60%; } @include tab { top: 50%; left: 50%; transform: translateY(-50%) translateX(-50%); width: 500px; } @include pc { width: 800px !important; top: 50% !important; transform: translateY(-50%) translateX(-50%) !important; } .global-links { @include tab { position: absolute; left: 55%; bottom: 0; transform: translateX(-0.7%); } @include pc { left: 75% !important; bottom: 55px; transform: translateX(-0.9%) !important; } } .contact-link { > a { color: $color-white; opacity: 0; @include fz(18); } margin: 10px 0 33px; @include tab { margin: 0 0 40px; } @include pc { margin: 0 0 55px; } } .sns-menu { opacity: 0; } .global-menu { @include tab { display: grid; grid-template-columns: repeat(2, 1fr); column-gap: 50px; position: relative; } @include pc { grid-template-columns: repeat(3, 1fr) !important; column-gap: 100px !important; } > li { margin-bottom: 25px; color: $color-white; > a { @include fz(15); line-height: 2; display: block; border-bottom: 1px solid $color-white; opacity: 0; } > .sub-menu { padding-top: 2rem; opacity: 0; > li { margin-bottom: 1.5rem; > a { @include fz(13); } } } } } &.show { @keyframes showIn { 0% { opacity: 0; } 100% { opacity: 1; } } @keyframes showRight { 0% { background-color: $color-gmenu; width: 100%; } 100% { background-color: transparent; width: 0; } } .global-menu { > li > a { position: relative; animation: showIn 0.8s ease-in forwards; } } .contact-link { > a { position: relative; animation: showIn 0.8s ease-in forwards; } } } } @keyframes slideRight { 0% { opacity: 0; transform: translateX(100px); } 100% { opacity: 1; transform: translateX(0); } } .slide-r { animation: slideRight 0.5s ease-in forwards; }
Lhankor_Mhy

2021/04/16 01:18

問題を把握しました。 原因もたぶん特定できていますが、どうやって修正すべきか悩ましいです。
gpsoft

2021/04/16 01:41

animateendイベントハンドラの中で、いろんなCSSクラスをaddしてますが、それをremoveしてる箇所が無いですね。それって、作戦通りですか? あと、クリックするたびにanimateendイベントハンドラが多重に仕込まれていくとか、インデントに全角スペースが使われてる箇所がある、などが気になります(いまのとこ害は無さそうですが……)。 実際に動かしてみたわけではないので、的外れだったらすみません。
ysmd

2021/04/16 05:58

ご指摘ありがとうございます! addしたクラスはanimateendの外でremoveしていました。 それをanimateendの中でremoveさせてみましたが、これが直接的な原因ではなさそうでした・・・
guest

回答1

0

ベストアンサー

原因ですが、イベントリスナの中でイベントを設定しているので、イベントが発火するごとにイベントリスナが増えていくことによります。
↓このようにすれば、何が起きているのかおおむね把握できると思います。

js

1 if ($globalNav.hasClass(CLASS_MOVE)) { 2 $navButton.on('click', () => { 3 console.log('closeclick') 4 $('.header-logo').css('display','block');

解決方法ですが、$navButton.on('click', () => {})の中に$navButton.on('click', () => {})を書くのをやめることです。

具体的には、

  • クリックイベント→開いたときの動作→if ($globalNav.hasClass(CLASS_MOVE))で分岐→イベントの設定または何もしない

ではなくて、

  • クリックイベント→if ($globalNav.hasClass(CLASS_MOVE))で分岐→開いたときの動作または閉じた時の動作

とすればいいかと思います。


なお、animationendイベントについても増えていっていますが、そっちは放置しても何とか動いているようです。
動いているもののおかしなコードではありますので、気になるのであれば、one()メソッドなどを使ってみるのもいいかもしれません。

.one() | jQuery API Documentation

投稿2021/04/16 03:13

Lhankor_Mhy

総合スコア36115

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

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

ysmd

2021/04/16 06:21 編集

ご回答ありがとうございます! いただいたアドバイスをもとにifで分岐させて開閉の処理を記述したところ問題となっていた、 開閉が同時に起こる問題はクリアされました。 もう一点アドバイスをいただければと思うのですが、メニューが開いたら閉じるという処理が動かない状態です・・・ console.logを仕込んでみたところ閉じる際のクリックが認識されていないようでした。 私の記述で間違いなどありましたらご指摘いただけますと幸いです。 if ($globalNav.hasClass(CLASS_MOVE) == false) { $navButton.on('click', (e) => { $globalNav.show(0, () => { $navButton.toggleClass(CLASS_ACTIVE) console.log('openclick') $('.header-logo').css('display','none'); $('.header-nav').css('display','none'); $('.dot').css('background-color','#fff'); $globalNav.addClass(CLASS_MOVE) $('.move #boxT4').on('animationend', () => { $globalMenu.addClass(CLASS_SHOW) $globalMenu.find('li > a').on('animationend', () => { for (let i = 0; i < $subMenu.length; i++) { $subMenu[i].classList.add(CLASS_SLIDE_R) } $snsMenu.addClass(CLASS_SLIDE_R) $body.addClass(CLASS_PREVENT) $globalNav.css('background-color', '#3b3b45') }) }) }) }) } else if($globalNav.hasClass(CLASS_MOVE)) { $navButton.on('click', () => { console.log('closeclick') $('.header-logo').css('display','block'); $('.header-nav').css('display','block'); $globalNav.css('background-color', 'transparent') $body.removeClass(CLASS_PREVENT) $globalNav.removeClass(CLASS_MOVE) $globalNav.addClass(CLASS_REMOVE) for (let i = 0; i < $subMenu.length; i++) { $subMenu[i].classList.remove(CLASS_SLIDE_R) } $snsMenu.removeClass(CLASS_SLIDE_R) $globalMenu.removeClass(CLASS_SHOW) $globalNav.on('animationend', () => { if ($globalNav.hasClass(CLASS_REMOVE)) { $globalNav.hide(0, () => { $globalNav.addClass(CLASS_REMOVE) }) } }) }) }
Lhankor_Mhy

2021/04/16 06:27

そうではなくて、 $navButton.on('click', (e) => { if(...) { 閉じる処理 }else{ 開く処理 } }) ということです。
ysmd

2021/04/19 03:09

返信が遅れて申し訳ありません! ご指摘ありがとうございます。 そのように修正してみます!
Lhankor_Mhy

2021/04/19 03:20

ご解決を祈ります。 ご不明点等ございましたら、ご遠慮なくコメント欄へどうぞ。
ysmd

2021/04/19 03:29

修正したところ、問題となっていた挙動は解決できそうです! ありがとうございます! 他のところで細かい調整は必要ですが、そこは自分でやれそうです!
Lhankor_Mhy

2021/04/19 04:36

お役に立てたようで何よりです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問