JavaScriptのonclickとclassListとsetTimeoutを使ったアニメーション付きの開閉ボタンのプログラム 結城永人 - 2019年5月10日 (金) サイトのハンバーガーメニュー(≡)などのコンテンツを出し入れできる開閉ボタンをJavaScriptで作成するプログラムには二つの大きな部分がある。 要素のクリックを判定するコンテンツに表示変更を行う JavaScriptのプログラムではクリックを判定するHTMLの要素を取得した上で、イベントハンドラのonclickからさらに表示変更を行うコンテンツにCSSのdisplayのnone(非表示)のようなデザインのclassをclassListプロパティのtoggle()(交互)メソッド、またはadd()とremove()(追加と削除)の二つのメソッドで付け替えて開閉ボタンを作成することができる。 目次開閉ボタンのJavaScriptの基本的なソースコードハンバーガーメニューのサンプルHTMLのonclick属性を使う場合JavaScriptのaddEventListener()メソッドを使う場合classの切り替えにadd()とremove()を使う場合アニメーション付きの開閉ボタンの作成スライダーの開くアニメーションのサンプルsetTimeout()メソッドでコンテンツの非表示を遅らせるスライダーの開いて閉じるアニメーションのサンプル 開閉ボタンのJavaScriptの基本的なソースコード Five colorful doors by djoanis / Pixabay JavaScriptのonclickハンドラとclassListのtoggle()メソッドを使う。 ハンバーガーメニューのサンプル (開閉ボタン) アイテム①アイテム②アイテム③ ※押すとメニュー画面が開閉する。 HTML <span class="svg-button"> <svg class="hamburger-menu-1" width="142" height="30" viewBox="0 0 142 30" role="img"><rect width="28" height="28" x="1" y="1" stroke="#8b008b" stroke-width="1px" fill="none"/><path d="M4 8h22M4 15h22M4 22h22" stroke="#8b008b" stroke-width="3px"/><text x="31" y="15" font-size="16px" dominant-baseline="central">(開閉ボタン)</text></svg> </span> <div class="sub-1 hidden"> <ul><li>アイテム①</li><li>アイテム②</li><li>アイテム③</li></ul> </div> CSS .svg-button svg {cursor:pointer;} .hidden {display:none;} .sub-1 {width:200px;background-color:#e6e6fa;margin-top:1em;margin-bottom:1em;} .sub-1 ul {list-style:none;padding:1em;} JavaScript var hbm1 = document.getElementsByClassName("hamburger-menu-1")[0]; var sb1 = document.getElementsByClassName("sub-1")[0]; hbm1.onclick = function(){ sb1.classList.toggle("hidden"); } JavaScriptの要素のクリックを判定するonclickプロパティは三つの仕方で、使える。サンプルは他にHTMLの開閉ボタンに関数名のonclick属性を追加したり、JavaScriptでaddEventListener()メソッドの引数にclickを入れたりして書き換えられる。 メニューを元のコンテンツに重ねる場合はCSSのpositionで位置取りを変えて同じところに合わせながらz-indexで重なる順番を変えて上に乗せたりすると良いと思う。 HTMLのonclick属性を使う場合 HTML <span class="svg-button"> <svg onclick="menu()" width="142" height="30" viewBox="0 0 142 30" role="img"><rect width="28" height="28" x="1" y="1" stroke="#8b008b" stroke-width="1px" fill="none"/><path d="M4 8h22M4 15h22M4 22h22" stroke="#8b008b" stroke-width="3px"/><text x="31" y="15" font-size="16px" dominant-baseline="central">(開閉ボタン)</text></svg> </span> <div class="sub-1 hidden"> <ul><li>アイテム①</li><li>アイテム②</li><li>アイテム③</li></ul> </div> CSS .svg-button svg {cursor:pointer;} .hidden {display:none;} .sub-1 {width:200px;background-color:#e6e6fa;margin-top:1em;margin-bottom:1em;} .sub-1 ul {list-style:none;padding:1em;} JavaScript var sb1 = document.getElementsByClassName("sub-1")[0]; function menu(){ sb1.classList.toggle("hidden"); } クリックを判定する三つの方法ではHTMLのonclick属性の使用は推奨されない。 これらの属性を使うことは避けるべきです。これは HTML を巨大化し可読性を下げます。情報と振る舞いの関心事が正しく分離されておらず、発見が困難なバグを生み出します。その上に、Event 属性の使い方はほとんどの場合、Wndow オブジェクト上のグローバル関数にスクリプトを晒す原因になります。これはグローバルの名前空間を汚染します。 Event 属性|MDN|Mozilla onclick属性はクリックを判定したいHTMLの特定の要素に記載できるから分かり易くて便利かも知れないけれどもJavaScriptのプログラムとしては他の方法を使った方が無難なんだ。 JavaScriptのaddEventListener()メソッドを使う場合 HTML <span class="svg-button"> <svg class="hamburger-menu-1" width="142" height="30" viewBox="0 0 142 30" role="img"><rect width="28" height="28" x="1" y="1" stroke="#8b008b" stroke-width="1px" fill="none"/><path d="M4 8h22M4 15h22M4 22h22" stroke="#8b008b" stroke-width="3px"/><text x="31" y="15" font-size="16px" dominant-baseline="central">(開閉ボタン)</text></svg> </span> <div class="sub-1 hidden"> <ul><li>アイテム①</li><li>アイテム②</li><li>アイテム③</li></ul> </div> CSS .svg-button svg {cursor:pointer;} .hidden {display:none;} .sub-1 {width:200px;background-color:#e6e6fa;margin-top:1em;margin-bottom:1em;} .sub-1 ul {list-style:none;padding:1em;} JavaScript var hbm1 = document.getElementsByClassName("hamburger-menu-1")[0]; var sb1 = document.getElementsByClassName("sub-1")[0]; hbm1.addEventListener("click", function(){ sb1.classList.toggle("hidden"); }, false); または function menu(){ sb1.classList.toggle("hidden"); } var hbm1 = document.getElementsByClassName("hamburger-menu-1")[0]; var sb1 = document.getElementsByClassName("sub-1")[0]; hbm1.addEventListener("click", menu, false); onclickハンドラからの関数処理とどう違うのか。 一度に1つのオブジェクトに割り当てることができる onclick ハンドラは1つだけです。より柔軟性があるため、代わりにEventTarget.addEventListener()メソッドを使用することをお勧めします。 GlobalEventHandlers.onclick|MDN|Mozilla addEventListener()メソッドは第二引数にコールバック関数を取って別々の関数処理を起動できるようになっている。 onclickハンドラだと複数のプログラムを仕込むのは前のものが後のもので上書きされて最終的に一つしか実行されない状態になってしまうから適さない。 HTMLとCSSのclassの切り替えにadd()とremove()を使う サンプルのソースコードではコンテンツを非表示にするCSSのdisplayのnoneのclassの付け外しによってハンバーガーメニューの開閉ボタンを動作させている。JavaScriptはclassListプロパティのtoggle()メソッドを使うけれども他にadd()メソッドとremove()メソッドでも同じようにプログラムを組めるんだ。 (開くボタン) (閉じるボタン) アイテム①アイテム②アイテム③ ※ボタン毎にメニュー画面が開くか閉じる。 HTML <span class="svg-button"> <svg class="hamburger-menu-2" width="142" height="30" viewBox="0 0 142 30" role="img"><rect width="28" height="28" x="1" y="1" stroke="#8b008b" stroke-width="1px" fill="none"/><path d="M4 8h22M4 15h22M4 22h22" stroke="#8b008b" stroke-width="3px"/><text x="31" y="15" font-size="16px" dominant-baseline="central">(開くボタン)</text></svg> </span> <div class="sub-2 hidden"> <span class="svg-button"> <svg class="close-button-2" width="142" height="30" viewBox="0 0 142 30" role="img"><rect width="28" height="28" x="1" y="1" stroke="#8b008b" stroke-width="1px" fill="none"/><path d="M4 4L26 26M26 4L4 26" stroke="#8b008b" stroke-width="3px"/><text x="31" y="15" font-size="16px" dominant-baseline="central">(閉じるボタン)</text></svg> </span> <ul><li>アイテム①</li><li>アイテム②</li><li>アイテム③</li></ul> </div> CSS .svg-button svg {cursor:pointer;} .hidden {display:none;} .sub-2 {width:200px;background-color:#e6e6fa;margin-top:1em;margin-bottom:1em;padding:1em;} .sub-2 ul {list-style:none;padding-left:0;} JavaScript var hbm2 = document.getElementsByClassName("hamburger-menu-2")[0]; var sb2 = document.getElementsByClassName("sub-2")[0]; var clb2 = document.getElementsByClassName("close-button-2")[0]; hbm2.onclick = function(){ hbm2.classList.add("hidden"); sb2.classList.remove("hidden"); }; clb2.onclick = function(){ hbm2.classList.remove("hidden"); sb2.classList.add("hidden"); } 開閉ボタンにclassListプロパティのadd()メソッドとremove()メソッドを使う場合、コンテンツの切り替えのスイッチを二つに分けるデザインに向いている。 スイッチが一つでコンテンツの表示と非表示の切り替えを行うには何等かの仕方で、コンテンツの状況を判定するための条件分岐のifを通さなくてはならない。するとclassがあれば付けて、なければ付けないという条件分岐を予め含んでいるtoggle()メソッドを使う方がプログラムは簡素化される。 アニメーション付きの開閉ボタンの作成 表示するコンテンツにCSSのanimationを付けておく。 スライダーの開くアニメーションのサンプル (開閉ボタン) アイテム①アイテム②アイテム③ ※押すとメニュー画面が開閉する。 HTML <span class="svg-button"> <svg class="hamburger-menu-3" width="142" height="30" viewBox="0 0 142 30" role="img"><rect width="28" height="28" x="1" y="1" stroke="#8b008b" stroke-width="1px" fill="none"/><path d="M4 8h22M4 15h22M4 22h22" stroke="#8b008b" stroke-width="3px"/><text x="31" y="15" font-size="16px" dominant-baseline="central">(開閉ボタン)</text></svg> </span> <div class="sub-3 hidden"> <ul><li>アイテム①</li><li>アイテム②</li><li>アイテム③</li></ul> </div> CSS .svg-button svg {cursor:pointer;} .hidden {display:none;} .sub-3 {width:200px;background-color:#e6e6fa;margin-top:1em;margin-bottom:1em;animation:slidein .2s ease-out;} .sub-3 ul {list-style:none;padding:1em;} @keyframes slidein {from {transform:translateX(-100%)} to {transform:translateX(0)}} JavaScript var hbm3 = document.getElementsByClassName("hamburger-menu-3")[0]; var sb3 = document.getElementsByClassName("sub-3")[0]; hbm3.onclick = function(){ sb3.classList.toggle("hidden"); } スライダーの場合のCSSのanimationにはコンテンツを移動させるtransformのtranslateX(横方向)やtranslateY(縦方向)が使い易いと思う。 もう一つ良く使われるCSSはopacityで、コンテンツの透明度を変えて徐々に浮かび上がらせたり(値は0から1)、沈み込ませたり(値は1から0)するデザインだ。 他にも縦に伸縮するアコーディオンメニューならばheightなどでコンテンツの高さを変化させると良い。 参考サイト高さ可変!CSSアニメーションでなめらかアコーディオン JavaScriptの開閉ボタンで厄介なのはCSSのdisplayのnoneによってコンテンツを消すときにアニメーションがかからない。 スライダーだとサンプルでもそうだけれども開くときはゆっくり動かすデザインが可能でも閉じるときは全く動かすデザインを付けられないからコンテンツは瞬時に消える他はなくなる。 setTimeout()メソッドでコンテンツの非表示を遅らせる 開閉ボタンの消すときのアニメーションは先んじてコンテンツを非表示にするdisplayのnoneのかかりをJavaScriptのsetTimeout()(停止)メソッドで時間差を付けて反対に遅らせると大丈夫なんだ。 スライダーの開いて閉じるアニメーションのサンプル (開閉ボタン) アイテム①アイテム②アイテム③ ※押すとメニュー画面が開閉する。 HTML <span class="svg-button"> <svg class="hamburger-menu-4" width="142" height="30" viewBox="0 0 142 30" role="img"><rect width="28" height="28" x="1" y="1" stroke="#8b008b" stroke-width="1px" fill="none"/><path d="M4 8h22M4 15h22M4 22h22" stroke="#8b008b" stroke-width="3px"/><text x="31" y="15" font-size="16px" dominant-baseline="central">(開閉ボタン)</text></svg> </span> <div class="sub-4 hidden"> <ul><li>アイテム①</li><li>アイテム②</li><li>アイテム③</li></ul> </div> CSS .svg-button svg {cursor:pointer;} .hidden {display:none;} .sub-4 {width:200px;background-color:#e6e6fa;margin-top:1em;margin-bottom:1em;animation:slidein .2s ease-out;} .sub-4 ul {list-style:none;padding:1em;} .slideout {animation:slideout .2s ease-out;} @keyframes slidein {from {transform:translateX(-100%)} to {transform:translateX(0)}} @keyframes slideout {from {transform:translateX(0%)} to {transform:translateX(-100%)}} JavaScript var hbm4 = document.getElementsByClassName("hamburger-menu-4")[0]; var sb4 = document.getElementsByClassName("sub-4")[0]; hbm4.onclick = function(){ if(sb4.classList.contains("hidden")){ sb4.classList.remove("hidden", "slideout"); } else { sb4.classList.add("slideout"); setTimeout(function(){ sb4.classList.add("hidden"); }, 200); }} 開閉ボタンの開くときと閉じるときのプログラムの内容が実質的に変わるから取り込んだ要素が非表示のclassを持つかどうかのcontains()メソッドなどを使った条件分岐のifをクリック判定後の関数処理に配置する必要がある。 サンプルはコンテンツに非表示のclassがあればremove()メソッドで非表示と同時に二回目以降に付けられるスライダーの閉じるアニメーションのclassを外す。コンテンツに非表示のclassがなければ先ずは開閉ボタンの閉じるアニメーションのclassを付けてからsetTimeout()メソッドで時間差をおいて後らせてから非表示のclassを付ける。 追記:アニメーションの遅延実行にはsetTimeout()よりもtransitionendやanimationendのイベントを使った方が動作でぴったり合わせられると分かった。 プログラムの注意点としてsetTimeout()メソッドのdelay(遅延)と閉じるアニメーションのanimation-duration(継続時間)を合わせなくてはならない。さもないとアニメーションが終わる前にコンテンツが消えたり、アニメーションが終わった後にコンテンツが現れたりしてしまう。 CSSのanimationとJavaScriptのsetTimeout()の設定時間は単位が違う。サンプルでは「.2s」と「200」に指定されている。前者のanimation-durationは一秒単位、後者のdelayは千分の一秒単位(値に単位の表記は不要)になっている。かりに同じ時間を指定するとしても両方が同じ記述にはならない。 detailsタグでサイトに開閉メニューを作る コメント 新しい投稿 前の投稿
細川慎二のどうにも泣けて来てしまうストリートライヴのアルトサックス サックス奏者の 細川慎二 のYouTubeチャンネルの Sax in the Night City で出ているサックスのストリートライヴの動画が美しい音色と相俟った街角の雰囲気の良さで心底と泣けて来るほどの感動を催させる。 細川慎二のアルトサックスの美しい音色が響き渡る街角の...
宜保愛子は本物の霊能力者だと考えられる三つの真実 昭和から平成にかけてテレビや雑誌で何度も大きく取り上げられて物凄く活躍した霊能力者の 宜保愛子 がいた。何気なく昔のテレビ番組を観ていたら霊視は嘘だったと思えない内容で、本当にびっくりした。昔、そんなに引き付けられて観ていたわけではないし、改めて霊能力が本当かどうかを確かめようと...
平田監督の白井球審の誤審への抗議はパワハラへの強力な対処法に他ならない 日本プロ野球で 佐々木朗希が完全試合を実現して 次の試合も八回まで無安打と無失点の状況で、次の試合はどうかと注目した4月24日の対オリックスバファローズ戦は初回の先頭打者の初球にヒットを打たれて五回に二失点を喫して連続の無安打と無失点が両方とも途絶えてしまった。 しかし予想外...
アドセンスのGDPRに日本でも対応しなくてはならない場合がある アドセンスの個人情報のCookieなどの使用に関してサイトの訪問者に同意を得なくてはならない法律としてEU(European Union/欧州連合)の GDPR (General Data Protection Regulation/EU一般データ保護規則)がある。外国の個人情報...
伊良部秀輝が自殺した原因はミッドライフクライシスによる鬱と飲酒だと考える プロ野球選手の 伊良部秀輝 が自殺したと知ってショックを受けたことがあった。もう十年以上前になる。2011年の夏、享年四十二と早過ぎたのに加えて大好きな投手の一人だったので、とても残念に感じた。 目次 伊良部秀輝が大好きだった記憶 負けても自分のスタイルを貫き通した 野球への...
日本人がジャニーズ事務所で行われた性加害よりも恐れていること イギリスの公共放送のBBC(British Broadcasting Corporation/英国放送協会)が日本のジャニーズ事務所の創業者の ジャニー喜多川 の性加害について取り上げたドキュメンタリーの J-POPの捕食者:秘められたスキャンダル に衝撃を受けた。 目次 ジ...
玉置浩二のメロディーは涙腺緩んで総毛立つ名曲中の名曲だ 玉置浩二 のYouTubeの公式チャンネルで、最も気に入りの メロディー のライブ版が追加されていた。曲自体をちゃんと聴いたのは約二十五年振りかも知れないけど、しかし初めての内容から以前にも況して大変な感動を覚えることになった。 玉置浩二 『メロディー』Live at Tok...
沖雅也の涅槃への自殺と双極性障害 かつて俳優の 沖雅也 の自殺が伝えられたとき、遺書の言葉とされた「おやじ、涅槃でまっている」と共に何なのかと疑問を感じたのを良く覚えている。聞き慣れない「涅槃」という言葉が入っても何十年も過ぎた今振り返っても自殺者の遺書として本当に珍しい表現だったと改めて驚く。 沖雅也が書い...
Imgurで画像URLと埋め込みコードを取得する方法 Imgur は自分でアップロードした画像については画像URL/直リンクを取得して他のサイトにHTMLのimgタグで表示させられる。 そして自分と他の人たちも含めて画像の埋め込みコードを取得して他のサイトのHTMLに、そのまま、記載して表示させられもする。 目次 Img...
Googleの誕生祝いでプロフィールアイコンに風船と紙吹雪が飛んで来た サイトを見ていたら妙な感じがするので、良く見てみるとGoogleサービスで、ログインして右上のプロフィールアイコンが出ているときに風船と紙吹雪が飛んで来ていることに気付いた。 Googleから久し振りに受け取った誕生祝い サマリー|Search Console| Goog...
コメント