生JSでハンバーガーメニューを作ろう

## はじめに

過去にjQueryで実装したハンバーガーメニューを生のJavaScriptに書き換えた。
備忘録的な意味も込めて書いていく。
~~実はjQueryほとんど学習してないない~~
~~使わないから~~

## 仕様について
今回作成したハンバーガメニューはスマホ時のみ表示
aタグのhref属性に移動したいidを記入する
\#とだけ記入すると画面最上部へスムーススクロールする
という条件で作成しています。


## コード


*jsだけだとどうしようもないのでhtmlとsassも貼っておく*

**HTML**

```html
<div id="hamburger__icon" class="hamburger__icon">
  <div class="hamburger__icon__bars">
    <div class="hamburger__icon__bars1"></div>
    <div class="hamburger__icon__bars2"></div>
    <div class="hamburger__icon__bars3"></div>
  </div>
</div>
      
<div id="hamburger__content" class="hamburger__content">
  <div class="hamburger__content-items">
    <div class="hamburger__content-item"><a href="">a</a></div>
    <div class="hamburger__content-item"><a href="">a</a></div>
    <div class="hamburger__content-item"><a href="">a</a></div>
    <div class="hamburger__content-item"><a href="">a</a></div>
    <div class="hamburger__content-item"><a href="">a</a></div>
  </div>
</div>
      
<div id="hamburger__background" class="hamburger__background"></div>
```
**SASS**

```scss
.hamburger__icon {
  position: fixed;
  top: 20px;
  right: 16px;
  z-index: 200;
  display: none;
  transition: 0.3s;

  @include mq('sp') {
    display: block;
  }

  &.active {
    transform: translateX(-200px);

    .hamburger__icon__bars1 {
      top: 8px;
      transform: rotate(-45deg);

    }
    
    .hamburger__icon__bars2 {
      display: none;
    }
    
    .hamburger__icon__bars3 {
      top: 8px;
      transform: rotate(45deg);
    }
  }
}

.hamburger__icon__bars {
  width: 22px;
  height: 20px;
  display: block;
  position: relative;
}

.hamburger__icon__bars1,
.hamburger__icon__bars2,
.hamburger__icon__bars3 {
  position: absolute;
  width: 22px;
  height: 4px;
  background: #fff;
  top: 0;
  left: 0;
  
}


.hamburger__icon__bars1 {
  top: 0;
}

.hamburger__icon__bars2 {
  top: 8px;
}

.hamburger__icon__bars3 {
  top: 16px;
}

.hamburger__content {
  width: 200px;
  height: 100%;
  background: #fff;
  position: fixed;
  top: 0;
  right: 0;
  box-shadow: 0 0 3px #00000029;
  z-index: 120;
  transform: translateX(105%);
  transition: 0.3s;


  &.active {
    transform: translateX(0%);
  }
}

.hamburger__content-items {

}

.hamburger__content-item {
  border-bottom: 1px dotted #707070;

  a {
    display: block;
    color: #707070;
    text-decoration: none;
    padding: 20px 145px 20px 20px;
  }
}

.hamburger__background {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 50;
  background: rgba(#000000, 0.8);
  display: none;
  transition: 0.3s;


  &.active {
    display: block;
  }
}
```
**JavaScript**

```javascript
// スムーススクロール
document.querySelectorAll('a[href^="#"]').forEach(link => {
  link.addEventListener('click', function(e) {
    e.preventDefault();
    const header = document.getElementById('header').clientHeight,
          id = this.getAttribute('href');
    let position = 0;
    if(id !== "#") {
      position = window.pageYOffset + document.querySelector(id).getBoundingClientRect().top - header;
    }

    window.scrollTo({
      top: position,
      behavior: 'smooth'
    })

    //ハンバーガーメニューを押したらスクロールして消える
    if (document.getElementById('hamburger__content').classList.contains('active')) {
      const timerID = setInterval(() => {
        if (window.pageYOffset === position){
          clearInterval(timerID);
          document.getElementById('hamburger__icon').classList.remove('active')
          document.getElementById('hamburger__content').classList.remove('active')
          document.getElementById('hamburger__background').classList.remove('active')
        }
      }, 16)
    }

  })
})

//メニューの表示非表示
document.getElementById('hamburger__icon').addEventListener('click', function() {
  this.classList.toggle('active')
  document.getElementById('hamburger__content').classList.toggle('active')
  document.getElementById('hamburger__background').classList.toggle('active')
})
```

## コードの説明

**HTML**と**SASS**は割愛。おしゃんなメニューです。
**JavaScript**

*JSのコメントアウトを確認してください*

- スムーススクロール
aタグのhref属性の値が#から始まる要素を取得して値に指定されているidへスムーススクロールする。
移動距離をheaderの高さ分ずらす
値に#だけが設定されている場合はページの最上部へスムーススクロールする

-  ハンバーガーメニューを押したらスクロールして消える
メニューを押して移動した際、自動でハンバーガーメニューを閉じる

- メニューの表示非表示
メニューの表示非表示を切り替えるためのclassの付与を実行

---
**カスタマイズ**
上記に加えてお好みでカスタムしてください
マスク部分をクリックした場合ハンバーガーメニューを閉じます。
*デフォルトではxアイコンを押した時/移動した時に閉じる*

```javascript
document.getElementById('hamburger__background').addEventListener('click', function() {
  this.classList.remove('active')
  document.getElementById('hamburger__icon').classList.remove('active')
  document.getElementById('hamburger__content').classList.remove('active')
})
```

## おわりに

動かない場合はhtmlにidが付与されているか確認してください。
そういえば最近だと生JSを勉強するならTSもいいよと言われる。
Type Script人気ですよね。