<button class="button-38 js-button-38"><span class="button-38__text">ボタン38</span><span class="button-38__circle"></span></button>
button.button-38.js-button-38
  span.button-38__text #{ text }
  span.button-38__circle
{
  "text": "ボタン38"
}
  • Content:
    $BLOCK_NAME: '.button-38';
    
    // 変数
    $color_white: #fff;
    $color_black: #000;
    
    #{ $BLOCK_NAME } {
      position: relative;
      padding: 36px 48px;
      overflow: hidden;
      color: $color_black;
      background: $color_white;
      border: 1px solid $color_black;
    
      &__circle {
        position: absolute;
        top: 50%;
        left: 50%;
        display: block;
        width: 0;
        height: 0;
        content: '';
        background: $color_white;
        border-radius: 50%;
        mix-blend-mode: exclusion;
        transition: width 0.3s, height 0.3s;
        transform: translate(-50%, -50%);
        @at-root #{ $BLOCK_NAME }.is-hover & {
          width: 60px;
          height: 60px;
        }
        @at-root #{ $BLOCK_NAME }.is-hover.is-clicked & {
          animation: button38Circle 1s forwards;
        }
      }
    }
    
    @keyframes button38Circle {
      90% {
        width: 400px;
        height: 400px;
        opacity: 0;
      }
      100% {
        width: 0;
        height: 0;
        opacity: 0;
      }
    }
    
  • URL: /components/raw/button38/button38.scss
  • Filesystem Path: src/components/buttons/21_40/button38/button38.scss
  • Size: 947 Bytes
  • Content:
    'use strict';
    
    import { gsap } from 'gsap';
    
    export const button38 = () => {
      const button = new Button38('js-button-38');
      button.init();
    }
    
    class Button38 {
      els: HTMLCollectionOf<Element>;
      circleSelector: string;
      hover: Boolean;
      clicked: Boolean;
      constructor(className: string) {
        this.els = document.getElementsByClassName(className);
        this.circleSelector = '.button-38__circle';
        this.hover = false;
        this.clicked = false;
      }
    
      /**
       * 初期化
       */
      init(): void {
        if (!this.els.length) return;
        this.onEnterHandler();
        this.onLeaveHandler();
        this.onMoveHandler();
        this.onClickHandler();
      }
    
      /**
       * 円要素の位置設定
       * @param el マウスイン/アウトした要素
       * @param event イベントオブジェクト
       * @param smooth スムーズに移動させる
       */
      setCirclePos(el: HTMLElement, event: MouseEvent, smooth: Boolean = false): void {
        // クリック済の場合、処理を終了
        if (this.clicked) return;
        const circleEl = <HTMLElement>el.querySelector(this.circleSelector);
        const clientRect = el.getBoundingClientRect();
        // 要素内におけるカーソル位置を取得
        const x = event.pageX - (clientRect.left + window.pageXOffset);
        const y = event.pageY - (clientRect.top + window.pageYOffset);
        // 要素の位置を設定
        if (smooth) {
          gsap.to(circleEl, {
            duration: 1,
            left: x,
            top: y,
          });
        } else {
          circleEl.style.left = x + 'px';
          circleEl.style.top = y + 'px';
        }
      }
    
      /**
       * カーソル進入時の処理
       */
      onEnterHandler(): void {
        [...this.els].forEach(el => {
          el.addEventListener('mouseenter', e => {
            this.setCirclePos(<HTMLElement>el, <MouseEvent>e);
            el.classList.add('is-hover');
          });
        });
      }
    
      /**
       * カーソル退出時の処理
       */
      onLeaveHandler(): void {
        [...this.els].forEach(el => {
          el.addEventListener('mouseleave', e => {
            console.log('test');
            this.setCirclePos(<HTMLElement>el, <MouseEvent>e);
            el.classList.remove('is-hover', 'is-clicked');
            // クリック済フラグを初期化
            this.clicked = false;
          });
        });
      }
    
      /**
       * カーソル移動時の処理
       */
      onMoveHandler(): void {
        [...this.els].forEach(el => {
          el.addEventListener('mousemove', e => {
            this.setCirclePos(<HTMLElement>el, <MouseEvent>e, true);
          });
        });
      }
    
      /**
       * クリック時の処理
       */
      onClickHandler(): void {
        [...this.els].forEach(el => {
          el.addEventListener('click', e => {
            el.classList.add('is-clicked');
            this.clicked = true;
          });
        });
      }
    }
    
  • URL: /components/raw/button38/button38.ts
  • Filesystem Path: src/components/buttons/21_40/button38/button38.ts
  • Size: 2.8 KB

No notes defined.