27
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Vue.jsで頑張るハンバーガーメニュー

Last updated at Posted at 2020-05-24

#はじめに#
「ハンバーガーメニューは古臭い」

最近、僕はその言葉を聞く機会が増えた。
それでも、僕はハンバーガーメニューが好きだ。

確かに、ハンバーガーメニューにはメニュー項目を探しにくいという欠点がある。
しかし、コンテンツを表示するエリアを広く使える、つまり表示エリアをほぼ占領しないというメリットがあるので時と場合によってはまだまだ現役で使えると僕は思っている。

ということで、Vue.jsを使ってハンバーガーメニューを実装してみる('ω')

とりあえず、完成形はこんな感じになる。

Humberger-Google-Chrome-2020-05-23-19-10-24.gif

サンプルサイトはこちらから
https://helloworld753315.github.io/vue_hamburger/

GitHubのリポジトリはこちらから
https://github.com/helloworld753315/vue_hamburger

では、実際に手を動かしてみよう!!

#参考ページ

#必要な知識(使う知識)

  • HTML,CSS
  • Vue.js
    • classの操作
    • イベントハンドリング
    • トランジション

#書く前に

まずは、classをバインドする方法の復習を少し...

class_bind.html
<div id="app">
    <h1 v-bind:class="{'color':color_bind}">色を変える</h1>
</div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    var app = new Vue({
      el: '#app',
      data: {
        color_bind:true
      }
    })
  </script>
style.css
.color{
  color: blue;
}

Vue.jsでclassを操作したい場合、v-bind:classを使うことでそれが可能になる。

例えば、上記のコードではcolorというclass名をcolor_bindというプロパティと結び付けている。
なので、color_bindがtrueならcolorクラスが付与され、falseなら付与されない。つまり、color_bindがtrueなら文字色が青になりfalseなら黒色のまま!

###1.trueの場合
image.png
###2.falseの場合
image.png

#実際に書いてみる

だらだらと説明しても面白くないので、とりあえず完成形。

index.html
<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Hamberger</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div id="app">
    <!--ハンバーガーメニューのボタン-->
    <div class="hamburger_btn" v-on:click='ActiveBtn=!ActiveBtn'>
      <span class="line line_01" v-bind:class="{'btn_line01':ActiveBtn}"></span>
      <span class="line line_02" v-bind:class="{'btn_line02':ActiveBtn}"></span>
      <span class="line line_03" v-bind:class="{'btn_line03':ActiveBtn}"></span>
    </div>
    <!--サイドバー-->
    <transition name="menu">
      <div class="menu" v-show="ActiveBtn">
          <ul>
              <li><a href="#">項目1</a></li>
              <li><a href="#">項目2</a></li>
              <li><a href="#">項目3</a></li>
              <li><a href="#">項目4</a></li>
              <li><a href="#">項目5</a></li>
          </ul>
      </div>
  </transition>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    var app = new Vue({
      el: '#app',
      data: {
        ActiveBtn: false
      }
    })
  </script>
</body>

</html>
style.css
/*ボタン*/
.hamburger_btn {
  position: fixed; /*常に最上部に表示したいので固定*/
  top: 0;
  right: 0;
  width: 70px;
  height: 72px;
  cursor: pointer;
  z-index: 50;
}

.hamburger_btn .line {
  position: absolute;
  top: 0;
  left: 20px;
  width: 32px;
  height: 2px;
  background: #333333;
  text-align: center;
}

.hamburger_btn .line_01 {
  top: 16px;
  transition: 0.4s ease;
}
.hamburger_btn .line_02 {
  top: 26px;
  transition: 0.4s ease;
}
.hamburger_btn .line_03 {
  top: 36px;
  transition: 0.4s ease;
}


.btn_line01 {
  transform: translateY(10px) rotate(-45deg);
  transition: 0.4s ease;
}
.btn_line02 {
  transition: 0.4s ease;
  opacity: 0;
}
.btn_line03 {
  transform: translateY(-10px) rotate(45deg);
  transition: 0.4s ease;
}

/*サイドバー*/
.menu-enter-active, .menu-leave-active {
  transition: opacity 0.4s;
}
.menu-enter, .menu-leave-to {
  opacity: 0;
}
.menu-leave, .menu-enter-to{
  opacity: 1;
}

.menu li {
  list-style: none;
  line-height: 1;
  padding: 1rem;
}
.menu {
  background-color: rgba(197, 197, 197, 0.671);
  z-index: 30;
  padding: 2rem 1rem;
  position: fixed;
  width: 20rem;
  height: 80rem;
  top: 0;
  right: 0;
}
.menu a {
  color: rgb(66, 66, 66);
  text-decoration: none;
  font-size: 1.2rem;
  padding: 0 2rem;
}
.menu ul{
  margin: 1rem;
  padding: 0;
}

##必要な機能

Vueを使ってハンバーガーメニューを作るには、次の2つの機能が必要

  • ボタン
    • ボタンを押したときにボタンが×に変わる
    • もう一度押したときに元に戻る
  • サイドバー
    • ボタンが押されたらメニューを表示する
    • もう一度ボタンが押されたらメニューを閉じる
    • 表示切替のときのアニメーション

##手順

###共通部分
v-on:clickを使うと、イベントの制御ができるので「ボタンがクリックされたらActiveBtnの真偽値を逆にする(反転する)」という処理を書く。

v-on:click='ActiveBtn=!ActiveBtn'

###ボタン
最初にやったv-bind:classを使ってActiveBtnがtrueだったらbtn_line01,
btn_line02,btn_line03のそれぞれのクラス属性を付与するようにする。
ざっくり表にするとこんな感じ。

|ActiveBtn|class属性|
|---|---|---|
|true|付与する|
|false|付与しない|

あとは、cssで開閉時のアニメーションを書いていくだけ。

cssの方を簡単に説明すると、classが付与されたらtranslaterotateでline_01とline_03の位置と角度を変更して、line_02の透明度を0にしているシンプルなものだ。

###サイドバー
v-showディレクティブを使ってサイドバーの表示切替の部分を作ろう!
共通部分として作ったActiveBtnのデータをv-show="ActiveBtn"と書いて紐づける。
そうすることで、ボタンを押したときに表示を切り替えることが可能になる。

最後に、サイドバーの表示切替時のアニメーションを作ろう!

表示切替のアニメーションにはVue.jsのトランジションという機能を使う。
わからない方のためにざっくり説明すると、cssトランジション・アニメーションを簡単に使えるようにした機能だ。
使う際は、<transion>タグで囲んで使う。名前を付けられるので今回はmenuとしておく。

<transion>タグで囲んだ場所には、トランジションクラスを使ってアニメーションを適用できる。
対象をDOMに追加するとき(表示するとき)のアニメーションはenter~、DOMから削除されるとき(非表示にするとき)はleave~を使う。

言葉で説明してもわかりにくいので、簡単な図を使って見ていこう(;・∀・)

transiton_enter.png

transiton_leave.png

図を見ると、サイドバーを表示するときは、.menu-enterで透明度0から始めて.menu-enter-toで透明度が1へと変化しているのが分かる。
また、サイドバーを非表示にするときは、.menu-leaveで透明度1から始めて、.menu-leave-toで透明度1に変化している。

書いたコードはこんな感じだ。


.menu-enter-active, .menu-leave-active {
  transition: opacity 0.4s;
}
.menu-enter, .menu-leave-to {
  opacity: 0;
}
.menu-leave, .menu-enter-to{
  opacity: 1;
}

補足しておくと、enter-activeleave-activeのところは透明度を0.4秒で変化させるという意味だ。

こんな感じの手順でコードを書いていけば、ハンバーガーメニューの完成(*'▽')

#最後に

長々と書いてしまいましたが、以上です
普段はTwitterでいろいろ呟いたりしてるので何か聞きたいこと、指摘などあればどんどん送ってほしいです!
https://mobile.twitter.com/helloworld193

27
30
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?