ボタンで開閉するハンバーガーメニューを作成します
キーワード:DOM, イベント(click), WebAnimationsAPI
作成例(完成イメージ)
- 作成例:https://ngsm-syr.github.io/javascript_navigation/
- コード:https://github.com/ngsm-syr/javascript_navigation/
【準備】フォルダ:javascript_navigation
①JavaScriptを書くための準備で作成したフォルダ(空のHTML、CSS、JavaScriptが入っている)を準備します。GitHubからもダウンロードできます。
②フォルダの名前を「javascript_navigation」に変更します
HTMLとCSSファイルの準備
まずボタン部分から作成します
▼index.html
<main>
<div id="btn-open">=</div>
<div id="menu">
<div id="btn-close">×</div>
<ul>
<li class="item"><a href="#">menu01</a></li>
<li class="item"><a href="#">menu02</a></li>
<li class="item"><a href="#">menu03</a></li>
<li class="item"><a href="#">menu04</a></li>
<li class="item"><a href="#">menu05</a></li>
</ul>
</div>
</main>
▼style.css
メニューを開くボタン→メニュー部分→メニューを閉じるボタンの順番に重ねますので、開くボタンから順に作成します。都度、ブラウザで確認しながら進めてください。
body {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#btn-open {
position: fixed;
top: 0;
right: 0;
width: 40px;
height: 40px;
background: #000;
color: #FFF;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
z-index: 100;
}
メニュー部分です。最終的には隠しますが、まずは見える状態で作成します。
#menu {
background: #000;
position: fixed;
top: 0;
right: 0;
width: 100%;
height: 100vh;
z-index: 200;
}
#menu ul {
list-style: none;
padding: 1rem 0;
}
#menu li {
text-align: center;
padding: 1rem 0;
}
#menu a {
color: #FFF;
text-decoration: none;
transition: color .5s;
}
#menu a:hover {
color: #666;
}
次に閉じるボタンを作成します。開くボタンと同じ設定になる部分が多いので、異なる部分のみ、別途設定します。閉じるボタンは一番手前にあるため、z-indexは、開くボタンやメニューよりも大きな値にします。
#btn-open,
#btn-close {
position: fixed;
top: 0;
right: 0;
width: 40px;
height: 40px;
background: #000;
color: #FFF;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
z-index: 100;
}
#btn-close {
z-index: 300;
}
画面全体にメニュー画面が広がることが確認できたら、visibilityとopacityを使って、メニューは見えない状態にします。
#menu {
background: #000;
position: fixed;
top: 0;
right: 0;
width: 100%;
height: 100vh;
z-index: 200;
visibility: hidden;
opacity: 0;
}
開くボタンの設定をする
開くボタンの実装から行います。
定数の定義
querySelectorを使って、開くボタン、閉じるボタン、メニュー部分をそれぞれ定数に格納します。
▼script.js
const open = document.querySelector('#btn-open');
const close = document.querySelector('#btn-close');
const menu = document.querySelector('#menu');
イベントの設定
開くボタンをクリックしたときにイベントが動作するようにします。まずはconsole.logを使って、動作するかどうかを確認します。
▼script.js
const menuOpen = () => {
console.log('hello');
}
open.addEventListener('click',menuOpen);
動作確認ができたらアニメーション効果をつけます。
const menuOpen = () => {
const keyframes = {
visibility: ['hidden','visible'],
opacity: [0,1]
}
const options = {
duration: 600,
easing: 'ease',
fill: 'forwards',
}
menu.animate(keyframes,options);
}
閉じるボタンは逆の動きを設定します。見える状態から見えない状態に変化するので、visibilityは、visible→hiddenに、opacityは、1→0にします。
const menuClose = () => {
const keyframes = {
visibility: ['visible','hidden'],
opacity: [1,0]
}
const options = {
duration: 600,
easing: 'ease',
fill: 'forwards',
}
menu.animate(keyframes,options);
}
close.addEventListener('click',menuClose);
【応用】文字が一つずつ表示されるようにする
「ギャラリー+アニメーション」で実装したアニメーション効果をつけると、メニュー項目を一つずつ表示されることができます。
初期状態ではメニュー項目を非表示にしておきます。
▼style.css
#menu li {
text-align: center;
padding: 1rem 0;
opacity: 0;
}
開くボタンを押したときに、アニメーションが動作するようにしたいので、同じ関数内に記述します。
▼script.js
// メニュー項目を配列に格納
const items = document.querySelectorAll('.item');
const menuOpen = () => {
const keyframes = {
visibility: ['hidden','visible'],
opacity: [0,1]
}
const options = {
duration: 600,
easing: 'ease',
fill: 'forwards',
}
menu.animate(keyframes,options);
// 項目を表示するアニメーション
items.forEach((item,index) => {
item.animate({opacity:[0,1]},{
duration: 600,
easing: 'ease',
fill: 'forwards',
delay: index * 200,
});
});
}
open.addEventListener('click',menuOpen);
項目を一つずつ表示するアニメーションは、上記のコードで実装できますが、2回目からうまく表示されず点滅したようになってしまいます。
これは、2回目からは、最初から表示された状態になってしまっているためです。そのため、閉じるボタンをクリックしたときに、項目を非表示にするコードを追加します。
const menuClose = () => {
const keyframes = {
visibility: ['visible','hidden'],
opacity: [1,0]
}
const options = {
duration: 600,
easing: 'ease',
fill: 'forwards',
}
menu.animate(keyframes,options);
items.forEach((item) => {
item.animate({opacity:[1,0]},{
duration: 600,
easing: 'ease',
fill: 'forwards',
});
});
}
close.addEventListener('click',menuClose);
参考書籍・リンク
- 「すらすらわかるJavaScript 新版」桜庭洋之,望月幸太郎, 翔泳社,2022
- 「1冊ですべて身につくJavaScript入門講座」Mana, SBクリエイティブ, 2023
- 「独習JavaScript」CodeMafia 外村将大, 翔泳社, 2021
- https://developer.mozilla.org/ja/docs/Web/API/Document_Object_Model/Introduction