<div class="scroll-anim-25">
    <div class="scroll-anim-25__item js-scroll-anim-25" data-percent="80"><canvas class="scroll-anim-25__chart"></canvas>
        <p class="scroll-anim-25__count">0</p>
    </div>
    <div class="scroll-anim-25__item js-scroll-anim-25" data-percent="96"><canvas class="scroll-anim-25__chart"></canvas>
        <p class="scroll-anim-25__count">0</p>
    </div>
    <div class="scroll-anim-25__item js-scroll-anim-25" data-percent="75"><canvas class="scroll-anim-25__chart"></canvas>
        <p class="scroll-anim-25__count">0</p>
    </div>
</div>
.scroll-anim-25
  each item in items
    .scroll-anim-25__item.js-scroll-anim-25(data-percent=item.percent)
      canvas.scroll-anim-25__chart
      p.scroll-anim-25__count 0
{
  "items": [
    {
      "percent": 80
    },
    {
      "percent": 96
    },
    {
      "percent": 75
    }
  ]
}
  • Content:
    $BLOCK_NAME: '.scroll-anim-25';
    
    // 変数
    
    #{ $BLOCK_NAME } {
      @include Mq(md) {
        display: flex;
        justify-content: space-around;
      }
    
      &__item {
        position: relative;
        width: 200px;
        height: 200px;
        margin: 0 auto;
        & + & {
          margin-top: 24px;
          @include Mq(md) {
            margin-top: 0;
          }
        }
      }
    
      &__chart {
        width: 200px;
        height: 200px;
      }
    
      &__count {
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        display: flex;
        align-items: center;
        justify-content: center;
        margin: auto;
        font-size: 48px;
        font-weight: bold;
      }
    }
    
  • URL: /components/raw/scroll-anim25/scroll-anim25.scss
  • Filesystem Path: src/components/scroll-anims/scroll-anim25/scroll-anim25.scss
  • Size: 666 Bytes
  • Content:
    'use strict';
    
    import {
      Chart,
      ArcElement,
      DoughnutController,
      LinearScale,
    } from 'chart.js';
    Chart.register(
      ArcElement,
      DoughnutController,
      LinearScale,
    );
    import { gsap } from 'gsap';
    import { ScrollTrigger } from 'gsap/ScrollTrigger';
    gsap.registerPlugin(ScrollTrigger);
    
    export const scrollAnim25 = () => {
      const itemEls = document.querySelectorAll('.js-scroll-anim-25');
      [...itemEls].forEach(el => {
        const anim = new Anim25(<HTMLElement>el);
        anim.init();
      });
    }
    
    class Anim25 {
      el: HTMLElement;
      ctx: CanvasRenderingContext2D;
      chart: any;
      animTime: number;
      chartColor: string;
      countEl: HTMLElement;
      constructor(el: HTMLElement) {
        this.el = el;
        if (!this.el) return;
        const canvas = <HTMLCanvasElement>this.el.querySelector('.scroll-anim-25__chart')
        this.ctx = canvas.getContext('2d');
        this.chart = null;
        this.animTime = 2000;
        this.chartColor = '#ff3333';
        this.countEl = this.el.querySelector('.scroll-anim-25__count');
      }
    
      /**
       * 初期化
       */
      init(): void {
        if (!this.el) return;
        this.scrollHandler();
      }
    
      /**
       * チャートアニメーション
       * @param values グラフの値
       */
      animChart(values: Array<number>): void {
        const self = this;
        this.chart = new Chart(this.ctx, {
          type: 'doughnut',
          data: {
            datasets: [
              {
                data: values,
                backgroundColor: [this.chartColor, 'transparent'],
                hoverBackgroundColor: [this.chartColor, 'transparent'],
                borderWidth: 0,
              },
            ],
          },
          options: {
            animation: {
              duration: self.animTime,
              // easing: 'linear',
            },
            cutout: '80%',
            maintainAspectRatio: true,
            responsive: false,
            plugins: {
              legend: {
                display: false,
              },
              tooltip: {
                enabled: false,
              },
            },
          },
        });
      }
    
      /**
       * カウントアップ
       * @param newVal カウントの値
       */
      animCount(newVal: number): void {
        const count = {
          val: 0,
        };
        gsap.to(count, {
          duration: this.animTime / 1000,
          val: newVal,
          roundProps: 'val',
          onUpdate: () => {
            this.countEl.textContent = count.val.toString();
          }
        });
      }
    
      /**
       * アニメーション開始
       */
      animStart(): void {
        const percent = Number(this.el.dataset.percent);
        this.animChart([percent, 100 - percent]);
        this.animCount(percent);
      }
    
      /**
       * スクロール連動のイベント設定
       */
      scrollHandler(): void {
        ScrollTrigger.create({
          trigger: this.el,
          start: 'top 70%',
          onEnter: self => {
            this.animStart();
            self.kill();
          }
        });
      }
    }
    
  • URL: /components/raw/scroll-anim25/scroll-anim25.ts
  • Filesystem Path: src/components/scroll-anims/scroll-anim25/scroll-anim25.ts
  • Size: 2.9 KB

No notes defined.