【JavaScript】ドロワーメニューの作り方

2018年12月17日
JavaScript

ブログのスマホレイアウト時に使いたかったので作成した。

サンプル

前提

下記の関数を定義済みの想定とする。

手順

ドロワーメニューのイベントを登録するオブジェクトを定義する

ドロワーメニューのイベントを登録するため、下記のオブジェクトを定義する。

function DrawerEventRegisterer() {
    let _isOpening = false;

    function _register() {
        const BUTTON = document.querySelector( '#drawer .button' );
        if ( BUTTON === null ) return;
      
        const CLOSE_AREA = document.querySelector( '#drawer .close-area' );
        if ( CLOSE_AREA === null ) return;

        const MENU = document.getElementById( 'drawer-menu' );
        if ( MENU === null ) return;
      
        const ACTIVE_CLASS_NAME = 'active';

        const onOpen = function() {
            _isOpening = true;

            BUTTON      .addClass( ACTIVE_CLASS_NAME );
            CLOSE_AREA  .addClass( ACTIVE_CLASS_NAME );
            MENU        .addClass( ACTIVE_CLASS_NAME );
        };

        const onClose = function() {
            _isOpening = false;

            BUTTON      .removeClass( ACTIVE_CLASS_NAME );
            CLOSE_AREA  .removeClass( ACTIVE_CLASS_NAME );
            MENU        .removeClass( ACTIVE_CLASS_NAME );
        };

        _registerPushedEvents( BUTTON, CLOSE_AREA, onOpen, onClose );
        _registerResizedEvent( BUTTON, onClose );
    }

    function _registerPushedEvents( button, closeArea, onOpen, onClose ) {
        const onPushedButton    = function() { if ( !_isOpening ) onOpen();  };
        const onPushedCloseArea = function() { if (  _isOpening ) onClose(); };

        button      .registerOnPushed( onPushedButton       );
        closeArea   .registerOnPushed( onPushedCloseArea    );
    }

    function _registerResizedEvent( button, onCompleted ) {
        const onResized = function() {
            if ( !_isOpening ) return;
          
            const DISPLAY = button.getStylesheetValue( 'display' );
            if ( DISPLAY !== 'none' ) return;
            
            onCompleted();
        };

        window.registerOnResized( onResized );
    }

    return {
        register: _register,
    };
};

各パーツを表示するために必要なHTMLを記述する

「ボタン」、「閉じるエリア( メニューを閉じるための領域 )」、「メニュー」を表示するため、下記のHTMLを適当な箇所( body要素の直下など )に記述する。

<div id="drawer">
  <div class="button">
    <div class="line"></div>
    <div class="line"></div>
    <div class="line"></div>
  </div>
  <div class="close-area"></div>
</div>

<div id="drawer-menu">
</div>

DOMContentLoadedイベントでオブジェクトを生成し、関数を呼ぶ

DrawerEventRegistererオブジェクトを生成し、register関数を呼ぶ処理をdocumentオブジェクトのDOMContentLoadedイベントに登録する。

document.addEventListener( 'DOMContentLoaded', function() {
    const DRAWER_EVENT_REGISTERER = new DrawerEventRegisterer;
    DRAWER_EVENT_REGISTERER.register();
} );

メニューで表示する要素を追加する

先ほど記述したHTMLの<div id="drawer-menu"></div>内にメニューで表示する要素を追加する。

<div id="drawer">
  <div class="button">
    <div class="line"></div>
    <div class="line"></div>
    <div class="line"></div>
  </div>
  <div class="close-area"></div>
</div>

<div id="drawer-menu">
	ここにメニュー内で表示する要素を追加
</div>

メニューに動きを付ける

「メニュー」に動きを付けるため、下記のCSSを記述する。

#drawer-menu {
    position: fixed;
    left: -100%;
    transition: left .3s ease-in;
}

#drawer-menu.active {
    left: 0;
    transition: left .5s cubic-bezier(0,.8,.6,1);
}

これでボタンを押した際に左側からメニューが出てくるようになる。

CSSで見た目を整える

後はHTMLの各要素に付いているIDとクラスを用いて、CSSで見た目を整える。