<div class="nl-py-8 nl-bg-blue">
    <div class="nl-container nl-text-white">
        <div class="nl-max-w-2xl nl-m-auto nl-flex md:nl-flex-row nl-flex-col nl-flex-align-center nl-flex-justify-center nl-text-center">
            <figure class="nl-c-stat" data-percent="40">
                <div class="nl-mb-3 md:nl-mb-0 nl-mt-0 md:nl-mr-4">
                    <svg class="nl-text-white" height="102" width="102" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 114 114" style="enable-background:new 0 0 102 102; --inner-stroke: currentColor; --outer-stroke: var(--nl-white); transform: rotate(-90deg)" aria-hidden="true">
                        <circle class="nl-c-stat_inner" stroke="var(--inner-stroke)" fill="transparent" stroke-width="1" cx="57" cy="57" r="49"></circle>
                        <circle class="nl-c-stat_outer" stroke="var(--outer-stroke)" fill="transparent" stroke-width="10" cx="57" cy="57" r="49"></circle>
                        <text class="nl-c-stat_text nl-font-museo nl-text-xl" dominant-baseline="central" x="25%" y="-50%" fill="currentColor" data-output>40%</text>
                    </svg>
                </div>
                <div>
                    <figcaption class="nl-text-xl nl-mb-0">
                        <span class="nl-u-sr-only">40%</span>Label here
                    </figcaption>
                </div>
            </figure>
        </div>
    </div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.6.1/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.6.1/ScrollTrigger.min.js"></script>
<script>
    (function() {
        const components = document.querySelectorAll('.nl-c-stat');
        // Bail if no stat outer found on page
        if (!components.length) return;
        document.addEventListener('DOMContentLoaded', event => {
            Array.from(components).forEach(component => {
                const dial = component.querySelector('.nl-c-stat_outer'),
                    percent = parseInt(component.dataset.percent),
                    text = component.querySelector('[data-output]');
                if (dial) {
                    console.log(dial)
                    gsap.to(dial, {
                        scrollTrigger: dial,
                        strokeDashoffset: getStrokeDashoffset(percent)
                    })
                }
                if (text) {
                    console.log(text)
                    gsap.from(text, {
                        textContent: 0,
                        duration: 1,
                        scrollTrigger: dial,
                        stagger: {
                            onUpdate: function() {
                                this.targets()[0].innerHTML = Math.ceil(parseInt(this.targets()[0].textContent)) + '%';
                            },
                        }
                    })
                }
            });
        })

        function getStrokeDashoffset(percent) {
            let min = -308;
            if (percent < 0) percent = 0;
            if (percent > 100) percent = 100;
            return min * percent / 100 + min;
        }
    })();
</script>
<div class="nl-py-8 nl-bg-blue">
  <div class="nl-container nl-text-white">
    <div class="nl-max-w-2xl nl-m-auto nl-flex md:nl-flex-row nl-flex-col nl-flex-align-center nl-flex-justify-center nl-text-center">
      <figure class="nl-c-stat" data-percent="40">
        <div class="nl-mb-3 md:nl-mb-0 nl-mt-0 md:nl-mr-4">
          <svg class="nl-text-white" height="102" width="102" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 114 114" style="enable-background:new 0 0 102 102; --inner-stroke: currentColor; --outer-stroke: var(--nl-white); transform: rotate(-90deg)" aria-hidden="true">
              <circle class="nl-c-stat_inner" stroke="var(--inner-stroke)" fill="transparent" stroke-width="1" cx="57" cy="57" r="49"></circle>
              <circle class="nl-c-stat_outer" stroke="var(--outer-stroke)" fill="transparent" stroke-width="10" cx="57" cy="57" r="49"></circle>
              <text class="nl-c-stat_text nl-font-museo nl-text-xl" dominant-baseline="central" x="25%" y="-50%" fill="currentColor" data-output>40%</text>
          </svg>
        </div>
        <div>
          <figcaption class="nl-text-xl nl-mb-0">
            <span class="nl-u-sr-only">40%</span>Label here
          </figcaption>
        </div>
      </figure>
    </div>
  </div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.6.1/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.6.1/ScrollTrigger.min.js"></script>
<script>
  (function() {
    const components = document.querySelectorAll( '.nl-c-stat' );

    // Bail if no stat outer found on page
    if( !components.length ) return;
    
    document.addEventListener( 'DOMContentLoaded', event => {
      Array.from(components).forEach( component => {
        
        const dial    = component.querySelector('.nl-c-stat_outer'),
              percent = parseInt( component.dataset.percent ),
              text    = component.querySelector('[data-output]');

        if( dial ) { 
          console.log(dial)         
          gsap.to( dial, {
            scrollTrigger: dial,
            strokeDashoffset: getStrokeDashoffset( percent )
          })
        }
        
        if( text ) { 
          console.log(text)         
          gsap.from(text, {
            textContent: 0,
            duration: 1,
            scrollTrigger: dial,
            stagger: {
              onUpdate: function() {
                this.targets()[0].innerHTML = Math.ceil(parseInt(this.targets()[0].textContent)) + '%';
              },
            }
          })
        }
     
      });
    })
    
    function getStrokeDashoffset( percent ) {
      let min = -308;

      if( percent < 0 ) percent = 0;
      if( percent > 100 ) percent = 100; 

      return min * percent / 100 + min; 
    }
  })();
</script>
{
  "title": "Stat Counter"
}
  • Content:
    .nl-c-stat svg {
        transform: rotate(-90deg);
    }
    
    .nl-c-stat_outer {
        stroke-dasharray: 308;
        stroke-dashoffset: -308;
    }
    
    .nl-c-stat_text {
        transform: rotate(90deg);
    }
  • URL: /components/raw/stat-counter/_stat-counter.scss
  • Filesystem Path: src/components/03-components/stat-counter/_stat-counter.scss
  • Size: 179 Bytes
  • Handle: @stat-counter
  • Preview:
  • Filesystem Path: src/components/03-components/stat-counter/stat-counter.hbs

No notes defined.