<div class="start-anim-01" id="js-start-anim-01">
    <div class="start-anim-01__content">
        <p class="start-anim-01__text"><span class="start-anim-01__count">0</span>%</p>
        <div class="start-anim-01__progress">
            <div class="start-anim-01__progress-val"></div>
        </div>
    </div>
</div>
<div><img src="https://picsum.photos/id/1000/1200/600" width="400px" /><img src="https://picsum.photos/id/1001/1200/600" width="400px" /><img src="https://picsum.photos/id/1002/1200/600" width="400px" /><img src="https://picsum.photos/id/1003/1200/600" width="400px" /><img src="https://picsum.photos/id/1004/1200/600" width="400px" /><img src="https://picsum.photos/id/1005/1200/600" width="400px" /><img src="https://picsum.photos/id/1006/1200/600" width="400px" /><img src="https://picsum.photos/id/1008/1200/600" width="400px" /><img src="https://picsum.photos/id/1009/1200/600" width="400px" /><img src="https://picsum.photos/id/1010/1200/600" width="400px" /></div>
.start-anim-01#js-start-anim-01
  .start-anim-01__content
    p.start-anim-01__text
      span.start-anim-01__count 0
      | %
    .start-anim-01__progress
      .start-anim-01__progress-val

div
  each item in items
    img(src=item.img, width='400px')
{
  "items": [
    {
      "img": "https://picsum.photos/id/1000/1200/600"
    },
    {
      "img": "https://picsum.photos/id/1001/1200/600"
    },
    {
      "img": "https://picsum.photos/id/1002/1200/600"
    },
    {
      "img": "https://picsum.photos/id/1003/1200/600"
    },
    {
      "img": "https://picsum.photos/id/1004/1200/600"
    },
    {
      "img": "https://picsum.photos/id/1005/1200/600"
    },
    {
      "img": "https://picsum.photos/id/1006/1200/600"
    },
    {
      "img": "https://picsum.photos/id/1008/1200/600"
    },
    {
      "img": "https://picsum.photos/id/1009/1200/600"
    },
    {
      "img": "https://picsum.photos/id/1010/1200/600"
    }
  ]
}
  • Content:
    $BLOCK_NAME: '.start-anim-01';
    
    // 変数
    $color_primary: #333;
    $color_progress_bg: #666;
    $color_progress_val: #fff;
    $color_white: #fff;
    $duration_default: 0.3s;
    
    #{ $BLOCK_NAME } {
      position: fixed;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      z-index: 9999;
      display: flex;
      align-items: center;
      justify-content: center;
      width: 100%;
      height: 100%;
      background: $color_primary;
    
      &__content {
        width: 100%;
      }
    
      &__text {
        margin-bottom: 8px;
        color: $color_white;
        text-align: center;
      }
    
      &__progress {
        position: relative;
        width: 100%;
        height: 2px;
        background: $color_progress_bg;
      }
    
      &__progress-val {
        position: absolute;
        top: 0;
        left: 0;
        display: block;
        width: 0;
        height: 2px;
        background: $color_progress_val;
        transition: width $duration_default;
      }
    }
    
  • URL: /components/raw/start-anim01/start-anim01.scss
  • Filesystem Path: src/components/start-anims/start-anim01/start-anim01.scss
  • Size: 890 Bytes
  • Content:
    'use strict';
    
    import { gsap } from 'gsap';
    
    export const startAnim01 = () => {
      const anim = new StartAnim01('js-start-anim-01');
      anim.init();
    }
    
    class StartAnim01 {
      el: HTMLElement;
      imgEls: NodeListOf<HTMLElement>;
      videoEls: NodeListOf<HTMLElement>;
      totalElNum: number;
      loadedElNum: number;
      loadedPercent: number;
      countEl: HTMLElement;
      progressValEl: HTMLElement;
      constructor(elId: string) {
        this.el = document.getElementById(elId);
        if (!this.el) return;
        this.imgEls = document.querySelectorAll('img:not([loading="lazy"])');
        this.videoEls = document.querySelectorAll('video');
        this.totalElNum = this.imgEls.length + this.videoEls.length;
        this.loadedElNum = 0;
        this.loadedPercent = 0;
        this.countEl = this.el.querySelector('.start-anim-01__count');
        this.progressValEl = this.el.querySelector('.start-anim-01__progress-val');
      }
    
      /**
       * 初期化
       */
      init(): void {
        if (!this.el) return;
        this.fixWindow();
        this.loadHandler();
      }
    
      /**
       * ウインドウ固定
       */
      fixWindow(): void {
        const scrollBarWidth = window.innerWidth - document.body.clientWidth;
        document.body.style.paddingRight = `${scrollBarWidth}px`;
        document.documentElement.style.overflow = 'hidden';
      }
    
      /**
       * ウインドウ固定を解除
       */
      clearWindow(): void {
        document.body.style.paddingRight = null;
        document.documentElement.style.overflow = null;
      }
    
      /**
       * 読み込み量の更新
       */
      updateLoader(): void {
        this.loadedElNum += 1;
        // 画像・動画以外の読込を考慮し、90%までの進捗表示にする
        const percent = Math.ceil(this.loadedElNum / this.totalElNum * 90);
        this.countEl.textContent = percent.toString();
        this.progressValEl.style.width = `${percent}%`;
        // 読み込み完了後、ローダーを非表示にする
        if (this.loadedElNum >= this.totalElNum) {
          setTimeout(() => {
            this.hideLoader();
          }, 500);
        }
      }
    
      /**
       * 要素ロード時のイベント設定
       */
      loadHandler(): void {
        // 画像のロードイベント
        [...this.imgEls].forEach(el => {
          el.addEventListener('load', () => {
            this.updateLoader();
          });
        });
        // 動画のロードイベント
        [...this.videoEls].forEach(el => {
          el.addEventListener('loadeddata', () => {
            this.updateLoader();
          });
        });
        // ページロード完了時のイベント
        window.onload = () => {
          this.loadedElNum = this.totalElNum;
          this.updateLoader();
        };
      }
    
      /**
       * ローダー非表示
       */
      hideLoader(): void {
        this.clearWindow();
        gsap.to(this.el, {
          duration: 1,
          opacity: 0,
          onComplete: () => {
            // ローダー要素を削除
            this.el.remove();
          }
        });
      }
    }
    
  • URL: /components/raw/start-anim01/start-anim01.ts
  • Filesystem Path: src/components/start-anims/start-anim01/start-anim01.ts
  • Size: 2.9 KB

参考