<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"
}
.nl-c-stat svg {
transform: rotate(-90deg);
}
.nl-c-stat_outer {
stroke-dasharray: 308;
stroke-dashoffset: -308;
}
.nl-c-stat_text {
transform: rotate(90deg);
}
No notes defined.