Skip to content

Instantly share code, notes, and snippets.

@ctrlsam
Created March 30, 2024 12:39
Show Gist options
  • Save ctrlsam/3e7b07e3009425b6c077eccdf0c38ef1 to your computer and use it in GitHub Desktop.
Save ctrlsam/3e7b07e3009425b6c077eccdf0c38ef1 to your computer and use it in GitHub Desktop.
<script>
const raised = 900;
const goal = 5000;
const widgetIndex = 0;
const countdownDate = "05/01/2024 00:00 AM"
function setCountdown(dt, id) {
var end = new Date(dt);
var _second = 1000;
var _minute = _second * 60;
var _hour = _minute * 60;
var _day = _hour * 24;
var timer;
function showRemaining() {
var now = new Date();
var distance = end - now;
if (distance < 0) {
clearInterval(timer);
document.getElementsByClassName(id)[widgetIndex].innerHTML = '0';
return;
}
var days = Math.floor(distance / _day);
document.getElementsByClassName(id)[widgetIndex].innerHTML = days;
}
timer = setInterval(showRemaining, 1000);
}
function formatToMoneyString(value, shorten = false) {
return `$${new Intl.NumberFormat('en-US').format(value)}`;
}
function updatePercentage() {
const percentageReached = (raised / goal) * 100;
const raisedElement = document.getElementsByClassName('raised-number')[widgetIndex];
const goalElement = document.getElementsByClassName('goal')[widgetIndex];
const percentageElement = document.getElementsByClassName('raised-percentage')[widgetIndex];
const progressBar = document.getElementsByClassName('progress')[widgetIndex];
goalElement.innerHTML = formatToMoneyString(goal);
percentageElement.innerHTML = percentageReached.toFixed(2) + "%" // Fixed to 2 decimal places for cleanliness
// Define the animation as a function so it can be called by the observer
const startAnimations = () => {
let currentRaised = 0;
const increment = raised / 100;
const duration = 1000;
const intervalTime = duration / 100;
const counterInterval = setInterval(() => {
currentRaised += increment;
if (currentRaised >= raised) {
currentRaised = raised;
clearInterval(counterInterval);
}
raisedElement.innerHTML = formatToMoneyString(Math.floor(currentRaised)) + " Raised";
}, intervalTime);
// Reset and animate progress bar width
progressBar.style.width = '0%';
requestAnimationFrame(() => {
progressBar.animate([
{ width: '0%' },
{ width: percentageReached + '%' }
], {
duration: 1000,
fill: 'forwards'
});
});
// Disconnect the observer once animation is started to avoid re-triggering
observer.disconnect();
};
// Setup Intersection Observer
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// Element is in view, start animations
startAnimations();
}
});
}, {
root: null, // observing viewport
rootMargin: '0px',
threshold: 0.1 // Trigger when 10% of the element is in view
});
// Observe the progress bar element
observer.observe(document.getElementsByClassName('countdown-wrap')[widgetIndex]);
}
window.onload = function () {
setCountdown(countdownDate, 'countdown');
updatePercentage();
};
</script>
<div class="countdown-wrap">
<div style="display: flex; flex-direction: column;">
<div class="raised-number"></div>
<div class="glass">
<div class="progress">
</div>
</div>
</div>
<div style="display: flex;">
<div class="goal-stat">
<span class="goal-number raised-percentage"></span> <!-- eg. 16%-->
<span class="goal-label">Funded</span>
</div>
<div class="goal-stat">
<span class="goal-number">
<div class="countdown"></div>
</span>
<span class="goal-label">Days to Go</span>
</div>
<div class="goal-stat">
<span class="goal-number goal"></span> <!-- eg. $2,000-->
<span class="goal-label">Goal</span>
</div>
</div>
</div>
<style>
.countdown-wrap {
width: 100%;
padding: 20px 0px 20px;
font-family: arial;
max-width: 650px;
font-family: 'Nunito', sans-serif;
}
.raised-number {
font-size: 32px;
text-align: left;
line-height: 50px;
color: #FFF;
@media only screen and (max-width : 640px) {
text-align: center;
}
}
.glass {
width: 100%;
height: 20px;
background: #c7c7c7;
border-radius: 10px;
float: left;
overflow: hidden;
}
.progress {
float: left;
width: 16%;
height: 20px;
background: rgb(142, 179, 95);
z-index: 333;
}
.goal-stat {
width: 25%;
padding: 10px;
float: left;
margin: 0;
color: #FFF;
@media only screen and (max-width : 640px) {
width: 50%;
text-align: center;
}
}
.goal-number,
.goal-label {
display: block;
}
.goal-number {
font-weight: bold;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment