A simple & sleek New year countdown animation made using GSAP.
A Pen by Animated Creativity on CodePen.
A simple & sleek New year countdown animation made using GSAP.
A Pen by Animated Creativity on CodePen.
<div class="holder"> | |
<div class="new-year"> | |
</div> | |
</div> |
/* Timelines could have been written in a better way, I am sorry if I wrote them in a hurry. :D */ | |
(function() { | |
var animation = { | |
newYear: document.querySelector(".new-year"), | |
range: function(min,max) { | |
return Math.floor(Math.random() * (max - min + 1) + min); | |
}, | |
get period() { | |
var dateFuture = new Date(new Date().getFullYear() + 1, 0, 1); | |
var dateNow = new Date(); | |
var seconds = Math.floor((dateFuture - (dateNow))/1000); | |
var minutes = Math.floor(seconds/60); | |
var hours = Math.floor(minutes/60); | |
var days = Math.floor(hours/24); | |
hours = hours-(days*24); | |
minutes = minutes-(days*24*60)-(hours*60); | |
seconds = seconds-(days*24*60*60)-(hours*60*60)-(minutes*60); | |
return { | |
year: new Date().getFullYear() + 1, | |
days: days, | |
hours: hours, | |
minutes: minutes, | |
seconds: seconds | |
} | |
}, | |
element: function(parent, type, className, html) { | |
var element = document.createElement(type); | |
element.className = className; | |
if (typeof html !== "undefined") element.innerHTML = html; | |
parent.appendChild(element); | |
return element; | |
}, | |
year: function(className) { | |
var timeline = new TimelineMax(); | |
var year = animation.element(animation.newYear, "div", className); | |
for (var i=0; i<=String(animation.period.year).length-1; i++) { | |
var digit = animation.element(year, "div", "digit", String(animation.period.year).substr(i, 1)); | |
digit.style.top = (0 - (digit.clientHeight * 2)) + "px"; | |
timeline | |
.to(digit, 0.5, {top: 0, opacity: 1, ease: Bounce.easeOut}); | |
} | |
return year; | |
}, | |
animate: function() { | |
var year1 = animation.year("year year1"); | |
var year2 = animation.year("year year2"); | |
var controls = animation.element(animation.newYear, "div", "controls"); | |
var days = animation.element(controls, "div", "control days"); | |
var hours = animation.element(controls, "div", "control hours"); | |
var minutes = animation.element(controls, "div", "control minutes"); | |
var seconds = animation.element(controls, "div", "control seconds"); | |
animation.controls = { | |
controls: controls, | |
days: days, | |
hours: hours, | |
minutes: minutes, | |
seconds: seconds | |
}; | |
animation.render(); | |
var triangles = animation.element(year1, "div", "triangles"); | |
var fullTimeline = new TimelineMax(); | |
var triangleStorage = []; | |
for (var i=0; i<=50-1; i++) { | |
var timeline = new TimelineMax({repeat: -1}); | |
var triangle = animation.element(triangles, "div", "triangle"); | |
triangle.style.top = -50 + "px"; | |
var time = animation.range(0, 100) / 100; | |
var duration = 1; | |
var direction = animation.range(1, 2) == 1 ? -1 : 1; | |
timeline | |
.set(triangle, {scale: animation.range(10, 20) / 10}, time) | |
.to(triangle, duration * 0.5, {opacity: 1}, time) | |
.to(triangle, duration, {top: "200%", rotationZ: animation.range(180, 360) * direction, rotationX: animation.range(180, 360) * direction}, time) | |
.to(triangle, duration * 0.5, {opacity: 0}, time + (duration * 0.5)); | |
fullTimeline.add(timeline, 0); | |
triangleStorage.push(triangle); | |
} | |
var previousWidth = 0; | |
var checkWidth = function() { | |
if (Math.abs(previousWidth - year1.clientWidth) > 1) { | |
for (var i=0; i<=triangleStorage.length-1; i++) { | |
triangleStorage[i].style.left = (-5 + animation.range(0, year1.clientWidth)) + "px"; | |
} | |
previousWidth = year1.clientWidth; | |
} | |
setTimeout(checkWidth, 100); | |
} | |
checkWidth(); | |
return new TimelineMax() | |
.to(days, 0.5, {top: 0, opacity: 1}, 0) | |
.to(hours, 0.5, {top: 0, opacity: 1}, 0.25) | |
.to(minutes, 0.5, {top: 0, opacity: 1}, 0.5) | |
.to(seconds, 0.5, {top: 0, opacity: 1}, 0.75) | |
.set(triangles, {opacity: 1}, 3) | |
.add(fullTimeline, 3); | |
}, | |
plural: function(property) { | |
var period = animation.period; | |
if (String(period[property]).length <= 1) period[property] = "0" + period[property]; | |
return Number(period[property]) > 1 ? period[property] + " " + property : period[property] + " " + property.substr(0, property.length-1); | |
}, | |
render: function() { | |
animation.controls.seconds.innerHTML = animation.plural("seconds"); | |
animation.controls.minutes.innerHTML = animation.plural("minutes"); | |
animation.controls.hours.innerHTML = animation.plural("hours"); | |
animation.controls.days.innerHTML = animation.plural("days"); | |
requestAnimationFrame(animation.render); | |
} | |
}; | |
animation.animate(); | |
})(); |
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script> | |
<script src="https://showcase.ylo.one/fiverr/ad/app/build/script.js"></script> |
@import url('https://fonts.googleapis.com/css?family=Major+Mono+Display'); | |
.holder { | |
position: absolute; | |
background-color: #ffffff; | |
left: 0%; | |
top: 0%; | |
width: 100%; | |
height: 100%; | |
} | |
.new-year { | |
font-family: 'Major Mono Display', monospace; | |
color: #333333; | |
font-size: 20px; | |
position: absolute; | |
left: 50%; | |
top: 50%; | |
width: 100%; | |
transform: translateX(-50%) translateY(-50%); | |
text-align: center; | |
} | |
.year { | |
position: relative; | |
left: 50%; | |
display: table; | |
font-size: 6em; | |
transform: translateX(-50%); | |
} | |
.year2 { | |
transform: translateX(-50%) rotateX(180deg); | |
opacity: 0.2; | |
} | |
.digit { | |
display: inline-block; | |
margin: 0px; | |
padding: 0px; | |
position: relative; | |
opacity: 0; | |
} | |
.controls { | |
margin-top: 30px; | |
} | |
.control { | |
display: inline-block; | |
padding-left: 20px; | |
padding-right: 20px; | |
font-size: 0.8em; | |
border-left: 1px solid #333333; | |
opacity: 0; | |
position: relative; | |
top: 100px; | |
} | |
.control:first-child { | |
border-left: none; | |
} | |
.triangles { | |
position: absolute; | |
left: 0%; | |
top: 0%; | |
width: 100%; | |
height: 100%; | |
opacity: 0; | |
} | |
.triangle { | |
width: 0; | |
height: 0; | |
border-left: 5px solid transparent; | |
border-right: 5px solid transparent; | |
border-bottom: 5px solid #333333; | |
position: absolute; | |
opacity: 0; | |
} |
nam mới