<div class="menu-02" id="js-menu-02"><a class="menu-02__btn" href="#">
        <div class="menu-02__icon">
            <div class="menu-02__icon-bar"></div>
            <div class="menu-02__icon-bar"></div>
            <div class="menu-02__icon-bar"></div>
        </div>
    </a>
    <div class="menu-02__content">
        <div class="menu-02__bg">
            <div class="menu-02__bg-item"></div>
            <div class="menu-02__bg-item"></div>
            <div class="menu-02__bg-item"></div>
            <div class="menu-02__bg-item"></div>
        </div>
        <div class="menu-02__links">
            <li><a class="menu-02__link" href="#">LINK 01</a></li>
            <li><a class="menu-02__link" href="#">LINK 02</a></li>
            <li><a class="menu-02__link" href="#">LINK 03</a></li>
            <li><a class="menu-02__link" href="#">LINK 04</a></li>
        </div>
    </div>
</div>
.menu-02#js-menu-02
  a.menu-02__btn(href='#')
    .menu-02__icon
      .menu-02__icon-bar
      .menu-02__icon-bar
      .menu-02__icon-bar
  .menu-02__content
    .menu-02__bg
      .menu-02__bg-item
      .menu-02__bg-item
      .menu-02__bg-item
      .menu-02__bg-item
    .menu-02__links
      each link in links
        li
          a.menu-02__link(href=link.link) #{ link.text }
{
  "links": [
    {
      "link": "#",
      "text": "LINK 01"
    },
    {
      "link": "#",
      "text": "LINK 02"
    },
    {
      "link": "#",
      "text": "LINK 03"
    },
    {
      "link": "#",
      "text": "LINK 04"
    }
  ]
}
  • Content:
    $BLOCK_NAME: '.menu-02';
    
    // 変数
    $color_primary: #00bfa6;
    $color_white: #fff;
    $color_black: #4a4a4a;
    $duration_default: 0.5s;
    
    #{ $BLOCK_NAME } {
      &__btn {
        position: fixed;
        top: 0;
        right: 0;
        z-index: 2;
        display: flex;
        align-items: center;
        justify-content: center;
        width: 72px;
        height: 48px;
        background: $color_primary;
      }
    
      &__icon {
        position: relative;
        transform: translateY(-2px);
      }
    
      &__icon-bar {
        position: absolute;
        left: -15px;
        width: 30px;
        height: 2px;
        background: $color_white;
        transition: all $duration_default;
        transform-origin: center center;
        @at-root #{ $BLOCK_NAME }__btn:hover & {
          background: $color_black;
        }
        &:nth-child(1) {
          top: -10px;
          @at-root #{ $BLOCK_NAME }__btn.is-active & {
            top: 0;
            transform: rotate(-45deg);
          }
        }
        &:nth-child(2) {
          top: 0;
          @at-root #{ $BLOCK_NAME }__btn.is-active & {
            opacity: 0;
          }
        }
        &:nth-child(3) {
          top: 10px;
          @at-root #{ $BLOCK_NAME }__btn.is-active & {
            top: 0;
            transform: rotate(45deg);
          }
        }
      }
    
      &__content {
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        z-index: 1;
        display: none;
      }
    
      &__bg-item {
        position: absolute;
        top: 0;
        bottom: 0;
        width: 0;
        background: $color_primary;
        transform-origin: right;
        &:nth-child(1) {
          left: 0;
        }
        &:nth-child(2) {
          left: 25%;
        }
        &:nth-child(3) {
          left: 50%;
        }
        &:nth-child(4) {
          left: 75%;
        }
      }
    
      &__links {
        position: absolute;
        top: 50%;
        left: 50%;
        width: 100%;
        max-width: 300px;
        transform: translate(-50%, -50%);
      }
    
      &__link {
        display: block;
        padding: 6px;
        font-size: 24px;
        font-weight: bold;
        color: $color_white;
        text-align: center;
        opacity: 0;
        transition: color $duration_default;
        transform: translateX(-20px);
        &:hover {
          color: $color_black;
        }
      }
    }
    
  • URL: /components/raw/menu02/menu02.scss
  • Filesystem Path: src/components/menus/menu02/menu02.scss
  • Size: 2.2 KB
  • Content:
    'use strict';
    
    import { gsap } from 'gsap';
    
    export const menu02 = ()=> {
      const menu = new Menu02('js-menu-02');
      menu.init();
    }
    
    class Menu02 {
      el: HTMLElement;
      btnEl: HTMLElement;
      bgEls: NodeListOf<HTMLElement>;
      contentEl: HTMLElement;
      linkEls: NodeListOf<HTMLElement>;
      constructor(elId: string) {
        this.el = document.getElementById(elId);
        if (!this.el) return;
        this.btnEl = this.el.querySelector('.menu-02__btn');
        this.bgEls = this.el.querySelectorAll('.menu-02__bg-item');
        this.contentEl = this.el.querySelector('.menu-02__content');
        this.linkEls = this.el.querySelectorAll('.menu-02__link');
      }
    
      /**
       * 初期化
       */
      init(): void {
        if (!this.el) return;
        this.onClickHandler();
      }
    
      /**
       * メニューを開く
       */
      open(): void {
        this.btnEl.classList.add('is-active');
        const tl = gsap.timeline();
        tl.set(this.contentEl, {
          display: 'block'
        })
        .to(this.bgEls, {
          duration: .2,
          width: '26%',
          stagger: {
            each: 0.1
          }
        })
        .to(this.linkEls, {
          delay: .2,
          duration: .3,
          x: 0,
          opacity: 1
        });
      }
    
      /**
       * メニューを閉じる
       */
      close(): void {
        this.btnEl.classList.remove('is-active');
        const tl = gsap.timeline();
        tl.set(this.bgEls, {
          width: '25%'
        })
        .to(this.linkEls, {
          duration: .3,
          x: 20,
          opacity: 0
        })
        .to(this.bgEls, {
          delay: .2,
          duration: .2,
          scaleX: 0,
          stagger: {
            each: 0.1
          }
        })
        .set([this.contentEl, this.bgEls, this.linkEls], {
          clearProps: 'all'
        });
      }
    
      /**
       * ボタンクリック時の挙動設定
       */
      onClickHandler(): void {
        this.btnEl.addEventListener('click', e => {
          e.preventDefault();
          if (this.btnEl.classList.contains('is-active')) {
            this.close();
          } else {
            this.open();
          }
        });
      }
    }
    
  • URL: /components/raw/menu02/menu02.ts
  • Filesystem Path: src/components/menus/menu02/menu02.ts
  • Size: 2 KB

参考