WebDesign Dackel

Googleのアプリ一覧UIを作ってみる

Googleのアプリ一覧UIを作ってみる

Hatena0
Google+0
Pocket0
Feedly0

突然ですが、スキルアップには上手な人の真似をするのが良いみたいです。
Webデザインを上達したいなら、良いデザインのサイトを模写したり、プログラムが上達したいならGitHubなどでコードを追ってみたり、といった具合です。
ではUIデザインは?となった時に、マテリアルデザインなどで世間を賑わすGoogleさんがふと頭をよぎったので、今回はGoogleの採用しているUIを真似てみたいと思います。

作るもの

動作サンプル画像

DEMO
※一部CSSを使ったアニメーションを使用したりしているのでChrome, Safariでの確認をオススメします。とりあえずのサンプルなので、あまりブラウザ確認はしていませんのでご了承ください。

どこで使われているものかと言いますと、GoogleにPCでアクセスした際に、画面右上にあるリストアイコンをクリックした時のあれです。中にはGoogleが提供するアプリが詰まっています。
このUIのちゃんとした名前は分からなかったので、とりあえず「Googleアプリ一覧」と名づけておきます。

ぴんと来ない方のために、本家はこんな感じです。

Googleのアプリ一覧UI

まずは動きの分析から

UIを真似するにあたって、どんな挙動かを把握しておく必要がありますね。
細かい点は省略しますがざっと洗いだしたのが下記です。

  1. リストアイコンのクリックで9つのアプリ一覧を表示
  2. 「もっと見る」のクリックでさらに6つのアプリを表示
  3. またはアプリ一覧上でホイールスクロールすると2と同じ挙動
  4. 2,3の状態からスクロール位置を最上部に戻すと1の状態に戻る
  5. リストアイコンのクリックで非表示に
  6. またはアプリ一覧以外の画面クリックで非表示に

実装の方針と前提

実装するにあたって下記の点を意識していきます。

  • CSSで表現できる部分はJSで無理せずCSSに任せる
  • jQuery以外のライブラリは不使用で
  • IE、スマホ対応。やりません。
  • そして、あまりに細かい点は省略!笑 ただ、どんな事をしているかは把握する

最初は、jQueryも使わない予定だったのですが面倒になってしまったため使う方向にシフトしました。笑

実装したコード

一行一行説明をしていると長くなりそうなので、コードの中にコメントを書いています。

HTML:

<a href="#app-list" id="app-list-trigger"><i class="fa fa-reorder"></i></a>
<div id="app-list" class="">
  <div id="app-list-body">
    <ul class="app-list-group">
      <!-- 9つのアプリが続きます -->
    </ul>
    <ul class="app-list-group">
      <!-- のこり6つのアプリ -->
    </ul>
    <a href="#more" class="app-list-more app-list-more-transparent">さらにもっと</a>
  </div>
  <a href="#more" id="app-list-scroll-trigger" class="app-list-more">もっと見る</a>
</div>

JavaScript(jQuery):

;(function($, window, undefined){

  var $doc,
      $trigger,
      $body,
      $list,
      $item,
      $scrollTrigger;

  var MouseEvent = {
    CLICK : "click.app",
    SCROLL: "scroll.app",
    WHEEL : getMouseWheelEvent("app")
  };

  var isShow = false;


  // 初期化
  function initialize(){
    $doc = $(document);
    $trigger = $("#app-list-trigger");
    $list = $("#app-list");
    $body = $("#app-list-body");
    $scrollTrigger = $("#app-list-scroll-trigger");

    // トリガー(今回はアイコンマーク)のクリックに応じて、表示・非表示を行う
    $trigger.on(MouseEvent.CLICK, function(){
      if( isShow ) hideList();
      else showList();
      return false;
    });
  }


  // リストを表示
  function showList(){
    scrollDisable();

    // リストが表示されたら、それ以外の画面クリックで閉じるように
    $doc.on(MouseEvent.CLICK, function(e){
      hideList();
    });

    // 表示用クラスを設定後、documentのクリックに影響が出ないようにしておく
    $list
      .addClass("show")
      .on(MouseEvent.CLICK, function(e){
        e.stopPropagation();
      });

    // 「もっと見る」ボタンのクリックで、アニメーション付きでスクロール状態へ
    $scrollTrigger.on(MouseEvent.CLICK, function(e){
      e.preventDefault();
      scrollEnable(true);
    });

    // wheelevent内は多くコールされるため変数を外部化
    var original, delta;

    $body
      .on(MouseEvent.SCROLL, function(){
        // 一番上までスクロールしたらスクロールの状態を解除
        if( $body.scrollTop() === 0 && $list.hasClass("scroll") ){
          scrollDisable();
        }
      })
      .on(MouseEvent.WHEEL, function(e){
        // デフォルトのイベントを解除後、スクロール分を取得
        e.preventDefault();
        original = e.originalEvent;
        delta = original.deltaY ? -original.deltaY : original.wheelDelta ? original.wheelDelta : -(original.detail);

        // スクロール分を$bodyに割り当て
        $body.scrollTop( $body.scrollTop() - delta );

        // 下へのスクロールで尚且つ、表示状態なら、スクロール状態へ移行
        if( delta < 0 ){
          if( !$list.hasClass("scroll") ){
            scrollEnable(false);
          }
        }
      });

    // 表示フラグをたてておく
    isShow = true;
  }


  // リストを非表示
  function hideList(){
    // 非表示に
    $list.removeClass("show");

    // 表示時に割り当てたイベントを解除しておく
    $doc.off(MouseEvent.CLICK);
    $body
      .off(MouseEvent.SCROLL)
      .off(MouseEvent.WHEEL);

    // 表示フラグを解除
    isShow = false;
  }


  // スクロール状態を有効化
  function scrollEnable(useAnimation){
    $list.addClass("scroll");

    if( useAnimation === true ){
      $body.stop().animate({"scrollTop": 350}, 400, "swing");
    }
  }


  // スクロール状態を無効化
  function scrollDisable(){
    $list.removeClass("scroll");
  }

  // マウスホイールのイベントを取得
  function getMouseWheelEvent(prefix){
    var eventName = "onwheel" in document ? "wheel" : "onmousewheel" in document ? "mousewheel" : "DOMMouseScroll";
    prefix = prefix !== undefined ? "." + prefix : "";
    return eventName + prefix;
  }


  // DOMContentLoaded
  $(initialize);


}(jQuery, window));

もちろん、CSSも必要ですが、これは長くなるので載せませんでした。
それらしく見せるポイントとしては下記のような点かと思います。

  • スクロール状態に入った際のスクロールバーのデザイン
  • 高さが変わる際のちょっとしたアニメーション

サンプル用のファイルはGitHubにあげておきましたので、もし興味のある方はそちらでファイルを弄って確認してみてください。

サンプルファイル

まとめ

本家Googleではウィンドウの縦幅が小さい時にサイズを調整していたり、細かい部分で省略している箇所がありますが、動きとしては十分かなと思います。ただ、Googleの方が動きがスムーズな気が…。

作り始める前は簡単そうだな!とか思っていたのですが、いざ作り始めてみると調整が地味に大変で、実際に作ってみないと分からない部分が沢山ありました。とにかく手を動かしてみて経験を積むのが、スキルアップへの近道なのかなと思いました。

参考サイトなど