diff --git a/animated-countdown/index.html b/animated-countdown/index.html new file mode 100644 index 0000000..6a23395 --- /dev/null +++ b/animated-countdown/index.html @@ -0,0 +1,26 @@ + + + + + + + Animated Countdown + + +
+
+ 3 + 2 + 1 + 0 +
+

Get Ready

+
+ +
+

GO

+ +
+ + + diff --git a/animated-countdown/script.js b/animated-countdown/script.js new file mode 100644 index 0000000..3493444 --- /dev/null +++ b/animated-countdown/script.js @@ -0,0 +1,40 @@ +const nums = document.querySelectorAll('.nums span') +const counter = document.querySelector('.counter') +const finalMessage = document.querySelector('.final') +const replay = document.querySelector('#replay') + +runAnimation() + +function resetDOM() { + counter.classList.remove('hide') + finalMessage.classList.remove('show') + + nums.forEach((num) => { + num.classList.value = '' + }) + + nums[0].classList.add('in') +} + +function runAnimation() { + nums.forEach((num, idx) => { + const nextToLast = nums.length - 1 + + num.addEventListener('animationend', (e) => { + if (e.animationName === 'goIn' && idx !== nextToLast) { + num.classList.remove('in') + num.classList.add('out') + } else if (e.animationName === 'goOut' && num.nextElementSibling) { + num.nextElementSibling.classList.add('in') + } else { + counter.classList.add('hide') + finalMessage.classList.add('show') + } + }) + }) +} + +replay.addEventListener('click', () => { + resetDOM() + runAnimation() +}) diff --git a/animated-countdown/style.css b/animated-countdown/style.css new file mode 100644 index 0000000..04536e6 --- /dev/null +++ b/animated-countdown/style.css @@ -0,0 +1,126 @@ +@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap'); + +* { + box-sizing: border-box; +} + +body { + font-family: 'Roboto', sans-serif; + margin: 0; + height: 100vh; + overflow: hidden; +} + +h4 { + font-size: 20px; + margin: 5px; + text-transform: uppercase; +} + +.counter { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + text-align: center; +} + +.counter.hide { + transform: translate(-50%, -50%) scale(0); + animation: hide 0.2s ease-out; +} + +@keyframes hide { + 0% { + transform: translate(-50%, -50%) scale(1); + } + + 100% { + transform: translate(-50%, -50%) scale(0); + } +} + +.final { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%) scale(0); + text-align: center; +} + +.final.show { + transform: translate(-50%, -50%) scale(1); + animation: show 0.2s ease-out; +} + +@keyframes show { + 0% { + transform: translate(-50%, -50%) scale(0); + } + + 30% { + transform: translate(-50%, -50%) scale(1.4); + } + + 100% { + transform: translate(-50%, -50%) scale(1); + } +} + +.nums { + color: #3498db; + font-size: 50px; + position: relative; + overflow: hidden; + width: 250px; + height: 50px; +} + +.nums span { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%) rotate(120deg); + transform-origin: bottom center; +} + +.nums span.in { + transform: translate(-50%, -50%) rotate(0deg); + animation: goIn 0.5s ease-in-out; +} + +.nums span.out { + animation: goOut 0.5s ease-in-out; +} + +@keyframes goIn { + 0% { + transform: translate(-50%, -50%) rotate(120deg); + } + + 30% { + transform: translate(-50%, -50%) rotate(-20deg); + } + + 60% { + transform: translate(-50%, -50%) rotate(10deg); + } + + 100% { + transform: translate(-50%, -50%) rotate(0deg); + } +} + +@keyframes goOut { + 0% { + transform: translate(-50%, -50%) rotate(0deg); + } + + 60% { + transform: translate(-50%, -50%) rotate(20deg); + } + + 100% { + transform: translate(-50%, -50%) rotate(-120deg); + } +}