※この記事は最終更新日から10か月以上経過しています。内容が古い可能性があります。

Circular Fly-Out Navigation Menuの作り方

Circular Fly-Out Navigation MenuのBlogを参考にさせていただいてサークルをClick(Tap)すると「ぴょっこり」飛び出すサークルナビゲーションメニューを作ったので覚えがき。
Demo

circleMenu.min.jsを使ったサークルメニュー画像
Click(Tap)すると

circleMenu.min.jsを使ったサークルナビゲーションメニュー画像「Click(Tap)時」

メニューリスト(ul)でHTMLを追加します。

HTML

<div id="c-circle-nav" class="c-circle-nav">
      <button id="c-circle-nav__toggle" class="c-circle-nav__toggle">
        <span>Toggle</span>
      </button>
      <ul class="c-circle-nav__items">
        <li class="c-circle-nav__item">
          <a href="#" class="c-circle-nav__link">
            <center><img src="images/House.png"></center>
          </a>
        </li>
        <li class="c-circle-nav__item">
          <a href="#" class="c-circle-nav__link">
            <center><img src="images/Facebook.png"></center>
          </a>
        </li>
        <li class="c-circle-nav__item">
          <a href="#" class="c-circle-nav__link">
            <center><img src="images/Pinterest.png"></center>
          </a>
        </li>
        <li class="c-circle-nav__item">
          <a href="#" class="c-circle-nav__link">
            <center><img src="images/Twitter.png"></center>
          </a>
        </li>
        <li class="c-circle-nav__item">
          <a href="#" class="c-circle-nav__link">
            <center><img src="images/Google.png"></center>
          </a>
        </li>
      </ul>
    </div>

レスポンシブでも対応できるように下記のようなCSSを記述しました。

CSS

.c-circle-nav__toggle,
  .c-circle-nav__toggle span {
      transition: background 0.3s;
      -webkit-transition: background 0.3s;
  }
  .c-circle-nav {
      position: fixed;
      bottom: 12px;
      right: 12px;
      z-index: 1000;
      width: 48px;
      height: 48px;
      border-radius: 24px;
  }
  @media (min-width:480px)and (min-height:480px) {
      .c-circle-nav {
          width: 96px;
          height: 96px;
          border-radius: 48px;
      }
  }
  .c-circle-nav__items {
      display: block;
      list-style: none;
      position: absolute;
      z-index: 90;
      margin: 0;
      padding: 0;
  }
  .c-circle-nav__item {
      display: block;
      position: absolute;
      top: 0;
      left: 0;
      width: 48px;
      height: 48px;
      border-radius: 24px;
      opacity: 0;
      -webkit-transition-property: -webkit-transform,opacity;
      transition-property: transform,opacity;
      -webkit-transition-duration: 0.3s,.3s;
      transition-duration: 0.3s,.3s;
      -webkit-transition-timing-function: cubic-bezier(.35,-.59,.47,.97);
      transition-timing-function: cubic-bezier(.35,-.59,.47,.97);
  }
  .c-circle-nav__item:nth-child(1) {
      -webkit-transition-delay: 0.4s;
      transition-delay: 0.4s;
  }
  .c-circle-nav__item:nth-child(2) {
      -webkit-transition-delay: 0.3s;
      transition-delay: 0.3s;
  }
  .c-circle-nav__item:nth-child(3) {
      -webkit-transition-delay: 0.2s;
      transition-delay: 0.2s;
  }
  .c-circle-nav__item:nth-child(4) {
      -webkit-transition-delay: 0.1s;
      transition-delay: 0.1s;
  }
  .c-circle-nav__item:nth-child(5) {
      -webkit-transition-delay: 0s;
      transition-delay: 0s;
  }
  .c-circle-nav.is-active .c-circle-nav__item {
      -webkit-transition-timing-function: cubic-bezier(.35,.03,.47,1.59);
      transition-timing-function: cubic-bezier(.35,.03,.47,1.59);
      opacity: 1;
  }
  .c-circle-nav.is-active .c-circle-nav__item:nth-child(1) {
      -webkit-transition-delay: 0s;
      transition-delay: 0s;
      -webkit-transform: translate(-144px,0);
      -ms-transform: translate(-144px,0);
      transform: translate(-144px,0);
  }
  @media (min-width:480px)and (min-height:480px) {
      .c-circle-nav__item {
          width: 96px;
          height: 96px;
          border-radius: 48px;
      }
      .c-circle-nav.is-active .c-circle-nav__item:nth-child(1) {
          -webkit-transform: translate(-288px,0);
          -ms-transform: translate(-288px,0);
          transform: translate(-288px,0);
      }
  }
  .c-circle-nav.is-active .c-circle-nav__item:nth-child(2) {
      -webkit-transition-delay: 0.1s;
      transition-delay: 0.1s;
      -webkit-transform: translate(-134px,-56px);
      -ms-transform: translate(-134px,-56px);
      transform: translate(-134px,-56px);
  }
  @media (min-width:480px)and (min-height:480px) {
      .c-circle-nav.is-active .c-circle-nav__item:nth-child(2) {
          -webkit-transform: translate(-267px,-111px);
          -ms-transform: translate(-267px,-111px);
          transform: translate(-267px,-111px);
      }
  }
  .c-circle-nav.is-active .c-circle-nav__item:nth-child(3) {
      -webkit-transition-delay: 0.2s;
      transition-delay: 0.2s;
      -webkit-transform: translate(-102px,-102px);
      -ms-transform: translate(-102px,-102px);
      transform: translate(-102px,-102px);
  }
  @media (min-width:480px)and (min-height:480px) {
      .c-circle-nav.is-active .c-circle-nav__item:nth-child(3) {
          -webkit-transform: translate(-204px,-204px);
          -ms-transform: translate(-204px,-204px);
          transform: translate(-204px,-204px);
      }
  }
  .c-circle-nav.is-active .c-circle-nav__item:nth-child(4) {
      -webkit-transition-delay: 0.3s;
      transition-delay: 0.3s;
      -webkit-transform: translate(-56px,-134px);
      -ms-transform: translate(-56px,-134px);
      transform: translate(-56px,-134px);
  }
  @media (min-width:480px)and (min-height:480px) {
      .c-circle-nav.is-active .c-circle-nav__item:nth-child(4) {
          -webkit-transform: translate(-111px,-267px);
          -ms-transform: translate(-111px,-267px);
          transform: translate(-111px,-267px);
      }
  }
  .c-circle-nav.is-active .c-circle-nav__item:nth-child(5) {
      -webkit-transition-delay: 0.4s;
      transition-delay: 0.4s;
      -webkit-transform: translate(0,-144px);
      -ms-transform: translate(0,-144px);
      transform: translate(0,-144px);
  }
  .c-circle-nav__link {
      display: block;
      width: 100%;
      height: 100%;
      border-radius: 24px;
      box-shadow: inset 0 0 0 2px #fff;
  }
  @media (min-width:480px)and (min-height:480px) {
      .c-circle-nav.is-active .c-circle-nav__item:nth-child(5) {
          -webkit-transform: translate(0,-288px);
          -ms-transform: translate(0,-288px);
          transform: translate(0,-288px);
      }
      .c-circle-nav__link {
          border-radius: 48px;
      }
  }
  .c-circle-nav__link img {
      display: block;
      max-width: 100%;
      height: auto;
      padding-top: 15px;
  }
  .c-circle-nav__link:hover {
      box-shadow: inset 0 0 0 2px #e91e63;
  }
  .c-circle-nav__toggle {
      display: block;
      position: absolute;
      z-index: 100;
      margin: 0;
      padding: 0;
      width: 48px;
      height: 48px;
      background-color: #e91e63;
      font: inherit;
      font-size: 0;
      text-indent: -9999px;
      border-radius: 24px;
      cursor: pointer;
      border: none;
      -webkit-appearance: none;
      -moz-appearance: none;
      appearance: none;
      box-shadow: none;
  }
  @media (min-width:480px)and (min-height:480px) {
      .c-circle-nav__toggle {
          width: 96px;
          height: 96px;
          border-radius: 48px;
      }
  }
  .c-circle-nav__toggle.is-active,
  .c-circle-nav__toggle:focus,
  .c-circle-nav__toggle:hover {
      outline: 0;
      background-color: #e91e63;
  }
  .c-circle-nav__toggle span,
  .c-circle-nav__toggle span::after,
  .c-circle-nav__toggle span::before {
      display: block;
      position: absolute;
      height: 4px;
      background: #fff;
      border-radius: 1px;
  }
  .c-circle-nav__toggle span {
      top: 22px;
      left: 10px;
      right: 10px;
  }
  @media (min-width:480px)and (min-height:480px) {
      .c-circle-nav__toggle span,
      .c-circle-nav__toggle span::after,
      .c-circle-nav__toggle span::before {
          height: 8px;
          border-radius: 2px;
      }
      .c-circle-nav__toggle span {
          top: 44px;
          left: 20px;
          right: 20px;
      }
  }
  .c-circle-nav__toggle span::after,
  .c-circle-nav__toggle span::before {
      left: 0;
      width: 100%;
      content: "";
      -webkit-transition-duration: 0.3s,.3s;
      transition-duration: 0.3s,.3s;
      -webkit-transition-delay: 0.3s,0s;
      transition-delay: 0.3s,0s;
  }
  .c-circle-nav__toggle span::before {
      top: -8px;
      -webkit-transition-property: top,-webkit-transform;
      transition-property: top,transform;
  }
  .c-circle-nav__toggle span::after {
      bottom: -8px;
      -webkit-transition-property: bottom,-webkit-transform;
      transition-property: bottom,transform;
  }
  @media (min-width:480px)and (min-height:480px) {
      .c-circle-nav__toggle span::before {
          top: -16px;
      }
      .c-circle-nav__toggle span::after {
          bottom: -16px;
      }
  }
  .c-circle-nav__toggle.is-active span {
      background: 0 0;
  }
  .c-circle-nav__toggle.is-active span::before {
      top: 0;
      -webkit-transform: rotate(45deg);
      -ms-transform: rotate(45deg);
      transform: rotate(45deg);
      -webkit-transition-delay: 0s,.3s;
      transition-delay: 0s,.3s;
  }
  .c-circle-nav__toggle.is-active span::after {
      bottom: 0;
      -webkit-transform: rotate(-45deg);
      -ms-transform: rotate(-45deg);
      transform: rotate(-45deg);
      -webkit-transition-delay: 0s,.3s;
      transition-delay: 0s,.3s;
  }
  .c-mask {
      position: fixed;
      top: 0;
      left: 0;
      z-index: 900;
      visibility: hidden;
      opacity: 0;
      width: 100%;
      height: 100%;
      background-color: rgba(0,0,0,.8);
      -webkit-transition: opacity 0.3s,visibility 0.3s;
      transition: opacity 0.3s,visibility 0.3s;
  }
  .c-mask.is-active {
      opacity: 1;
      visibility: visible;
  }

js(jQuery)

「jquery.js」と外部ファイルとして「circleMenu.js」を記述します。

<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22https%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fjquery%2F1.11.3%2Fjquery.min.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22js%2FcircleMenu.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />

「circleMenu.js」の内容は下記のようになっています。

!function () {
    "use strict";
    function c() {
        s
            .classList
            .add(n),
        t
            .classList
            .add(n),
        i
            .classList
            .add(n)
    }
    function e() {
        s
            .classList
            .remove(n),
        t
            .classList
            .remove(n),
        i
            .classList
            .remove(n)
    }
    var s = document.querySelector("#c-circle-nav"),
        t = document.querySelector("#c-circle-nav__toggle"),
        i = document.createElement("div"),
        n = "is-active";
    i
        .classList
        .add("c-mask"),
    document
        .body
        .appendChild(i),
    t.addEventListener("click", function (s) {
        s.preventDefault(),
        t
            .classList
            .contains(n)
            ? e()
            : c()
    }),
    i.addEventListener("click", function () {
        e(),
        console.log("click")
    })
}();

これで、レスポンシブで使えるサークルメニューができました。

以上、今日の覚えがき。