Created
March 30, 2024 12:39
-
-
Save ctrlsam/3e7b07e3009425b6c077eccdf0c38ef1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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