See more on http://cssanimation.rocks
Forked from Donovan Hutchinson's Pen Basic animated clock.
<div class="demo-container clocks active bounce"> | |
<article class="clock station js-new-york"> | |
<section class="label">New York</section> | |
<section class="hours-container"> | |
<section class="hours"></section> | |
</section> | |
<section class="minutes-container"> | |
<section class="minutes"></section> | |
</section> | |
<section class="seconds-container"> | |
<section class="seconds"></section> | |
</section> | |
</article> | |
<article class="clock station js-london"> | |
<section class="label">London</section> | |
<section class="hours-container"> | |
<section class="hours"></section> | |
</section> | |
<section class="minutes-container"> | |
<section class="minutes"></section> | |
</section> | |
<section class="seconds-container"> | |
<section class="seconds"></section> | |
</section> | |
</article> | |
<article class="clock station js-tokyo"> | |
<section class="label">Tokyo</section> | |
<section class="hours-container"> | |
<section class="hours"></section> | |
</section> | |
<section class="minutes-container"> | |
<section class="minutes"></section> | |
</section> | |
<section class="seconds-container"> | |
<section class="seconds"></section> | |
</section> | |
</article> | |
</div> |
/* | |
* Main function to set the clock times | |
*/ | |
(function() { | |
// Initialise the locale-enabled clocks | |
initInternationalClocks(); | |
// Initialise any local time clocks | |
initLocalClocks(); | |
// Start the seconds container moving | |
moveSecondHands(); | |
// Set the intial minute hand container transition, and then each subsequent step | |
setUpMinuteHands(); | |
})(); | |
/* | |
* Set up an entry for each locale of clock we want to use | |
*/ | |
function getTimes() { | |
moment.tz.add([ | |
'Eire|GMT IST|0 -10|01010101010101010101010|1BWp0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00', | |
'Asia/Tokyo|JST|-90|0|', | |
'America/New_York|EST EDT|50 40|0101|1Lz50 1zb0 Op0' | |
]); | |
var now = new Date(); | |
// Set the time manually for each of the clock types we're using | |
var times = [ | |
{ | |
jsclass: 'js-tokyo', | |
jstime: moment.tz(now, "Asia/Tokyo") | |
}, | |
{ | |
jsclass: 'js-london', | |
jstime: moment.tz(now, "Eire") | |
}, | |
{ | |
jsclass: 'js-new-york', | |
jstime: moment.tz(now, "America/New_York") | |
} | |
]; | |
return times; | |
} | |
/* | |
* Set up the clocks that use moment.js | |
*/ | |
function initInternationalClocks() { | |
// Initialise the clock settings and the three times | |
var times = getTimes(); | |
for (i = 0; i < times.length; ++i) { | |
var hours = times[i].jstime.format('h'); | |
var minutes = times[i].jstime.format('mm'); | |
var seconds = times[i].jstime.format('ss'); | |
var degrees = [ | |
{ | |
hand: 'hours', | |
degree: (hours * 30) + (minutes / 2) | |
}, | |
{ | |
hand: 'minutes', | |
degree: (minutes * 6) | |
}, | |
{ | |
hand: 'seconds', | |
degree: (seconds * 6) | |
} | |
]; | |
for (var j = 0; j < degrees.length; j++) { | |
var elements = document.querySelectorAll('.active .' + times[i].jsclass + ' .' + degrees[j].hand); | |
for (var k = 0; k < elements.length; k++) { | |
elements[k].style.webkitTransform = 'rotateZ('+ degrees[j].degree +'deg)'; | |
elements[k].style.transform = 'rotateZ('+ degrees[j].degree +'deg)'; | |
// If this is a minute hand, note the seconds position (to calculate minute position later) | |
if (degrees[j].hand === 'minutes') { | |
elements[k].parentNode.setAttribute('data-second-angle', degrees[j + 1].degree); | |
} | |
} | |
} | |
} | |
// Add a class to the clock container to show it | |
var elements = document.querySelectorAll('.clock'); | |
for (var l = 0; l < elements.length; l++) { | |
elements[l].className = elements[l].className + ' show'; | |
} | |
} | |
/* | |
* Starts any clocks using the user's local time | |
*/ | |
function initLocalClocks() { | |
// Get the local time using JS | |
var date = new Date; | |
var seconds = date.getSeconds(); | |
var minutes = date.getMinutes(); | |
var hours = date.getHours(); | |
// Create an object with each hand and it's angle in degrees | |
var hands = [ | |
{ | |
hand: 'hours', | |
angle: (hours * 30) + (minutes / 2) | |
}, | |
{ | |
hand: 'minutes', | |
angle: (minutes * 6) | |
}, | |
{ | |
hand: 'seconds', | |
angle: (seconds * 6) | |
} | |
]; | |
// Loop through each of these hands to set their angle | |
for (var j = 0; j < hands.length; j++) { | |
var elements = document.querySelectorAll('.local .' + hands[j].hand); | |
for (var k = 0; k < elements.length; k++) { | |
elements[k].style.transform = 'rotateZ('+ hands[j].angle +'deg)'; | |
// If this is a minute hand, note the seconds position (to calculate minute position later) | |
if (hands[j].hand === 'minutes') { | |
elements[k].parentNode.setAttribute('data-second-angle', hands[j + 1].angle); | |
} | |
} | |
} | |
} | |
/* | |
* Move the second containers | |
*/ | |
function moveSecondHands() { | |
var containers = document.querySelectorAll('.bounce .seconds-container'); | |
setInterval(function() { | |
for (var i = 0; i < containers.length; i++) { | |
if (containers[i].angle === undefined) { | |
containers[i].angle = 6; | |
} else { | |
containers[i].angle += 6; | |
} | |
containers[i].style.webkitTransform = 'rotateZ('+ containers[i].angle +'deg)'; | |
containers[i].style.transform = 'rotateZ('+ containers[i].angle +'deg)'; | |
} | |
}, 1000); | |
for (var i = 0; i < containers.length; i++) { | |
// Add in a little delay to make them feel more natural | |
var randomOffset = Math.floor(Math.random() * (100 - 10 + 1)) + 10; | |
containers[i].style.transitionDelay = '0.0'+ randomOffset +'s'; | |
} | |
} | |
/* | |
* Set a timeout for the first minute hand movement (less than 1 minute), then rotate it every minute after that | |
*/ | |
function setUpMinuteHands() { | |
// More tricky, this needs to move the minute hand when the second hand hits zero | |
var containers = document.querySelectorAll('.minutes-container'); | |
var secondAngle = containers[containers.length - 1].getAttribute('data-second-angle'); | |
console.log(secondAngle); | |
if (secondAngle > 0) { | |
// Set a timeout until the end of the current minute, to move the hand | |
var delay = (((360 - secondAngle) / 6) + 0.1) * 1000; | |
console.log(delay); | |
setTimeout(function() { | |
moveMinuteHands(containers); | |
}, delay); | |
} | |
} | |
/* | |
* Do the first minute's rotation, then move every 60 seconds after | |
*/ | |
function moveMinuteHands(containers) { | |
for (var i = 0; i < containers.length; i++) { | |
containers[i].style.webkitTransform = 'rotateZ(6deg)'; | |
containers[i].style.transform = 'rotateZ(6deg)'; | |
} | |
// Then continue with a 60 second interval | |
setInterval(function() { | |
for (var i = 0; i < containers.length; i++) { | |
if (containers[i].angle === undefined) { | |
containers[i].angle = 12; | |
} else { | |
containers[i].angle += 6; | |
} | |
containers[i].style.webkitTransform = 'rotateZ('+ containers[i].angle +'deg)'; | |
containers[i].style.transform = 'rotateZ('+ containers[i].angle +'deg)'; | |
} | |
}, 60000); | |
} | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/moment.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/locales.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.3.0/moment-timezone.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.3.0/moment-timezone-utils.min.js"></script> |
body { | |
margin: 0; | |
} | |
.demo-container.clocks { | |
background: #3cd19e; | |
padding: 0; | |
width: 100%; | |
height: 100vh; | |
margin: 0; | |
overflow: hidden; | |
} | |
.clock { | |
border-radius: 50%; | |
background: radial-gradient(#000, #000 0.1em, #fff 0.1em, #fff), #fff; | |
display: inline-block; | |
margin: 1%; | |
padding-bottom: 31%; | |
position: relative; | |
top: 50%; | |
width: 31%; | |
opacity: 0; | |
transform: translateY(-40%); | |
} | |
// Put in a no-js alternative so they're not invisible | |
.clock.show { | |
opacity: 1; | |
transform: translateY(-50%); | |
transition: all 2.5s 0.5s cubic-bezier(.12,1.03,.34,1); | |
} | |
.clock::after { | |
background: red; | |
border-radius: 50%; | |
content: ""; | |
position: absolute; | |
left: 50%; | |
top: 50%; | |
transform: translate(-50%, -50%); | |
width: 4%; | |
height: 4%; | |
z-index: 10; | |
} | |
.minutes-container, .hours-container, .seconds-container { | |
position: absolute; | |
top: 0; | |
right: 0; | |
bottom: 0; | |
left: 0; | |
} | |
.hours-container { | |
animation: rotate 43200s infinite linear; | |
} | |
.linear { | |
.minutes-container { | |
animation: rotate 3600s infinite linear; | |
} | |
.seconds-container { | |
animation: rotate 60s infinite linear; | |
} | |
} | |
.steps { | |
.minutes-container { | |
animation: rotate 3600s infinite steps(60); | |
} | |
.seconds-container { | |
animation: rotate 60s infinite steps(60); | |
} | |
} | |
.local.steps { | |
.minutes-container { | |
animation: none; | |
} | |
} | |
.bounce { | |
.minutes-container { | |
transition: transform 0.3s cubic-bezier(.4,2.08,.55,.44); | |
} | |
.seconds-container { | |
transition: transform 0.2s cubic-bezier(.4,2.08,.55,.44); | |
} | |
} | |
.hours { | |
background: #000; | |
width: 3.5%; | |
height: 40%; | |
position: absolute; | |
left: 48.25%; | |
top: 22%; | |
transform-origin: 50% 71%; | |
} | |
.minutes { | |
background: #000; | |
width: 3.5%; | |
height: 55%; | |
position: absolute; | |
left: 48.25%; | |
top: 7%; | |
transform-origin: 50% 78.5%; | |
} | |
.seconds { | |
background: red; | |
width: 1.5%; | |
height: 42%; | |
position: absolute; | |
left: 49.25%; | |
top: 20%; | |
transform-origin: 50% 71%; | |
z-index: 8; | |
} | |
.label { | |
background: #fff; | |
border-radius: 0.25em; | |
color: #000; | |
font-family: MyriadPro-Regular, 'Myriad Pro Regular', MyriadPro, 'Myriad Pro', Helvetica, Arial, sans-serif; | |
font-size: 1em; | |
font-weight: bold; | |
text-transform: uppercase; | |
padding: 0.5em 0.75em 0.25em; | |
position: absolute; | |
top: -4em; | |
left: 50%; | |
transform: translate(-50%, 0); | |
} | |
@keyframes rotate { | |
100% { | |
transform: rotateZ(360deg); | |
} | |
} | |
.clock.station { | |
background: #fff url(//cssanimation.rocks/assets/images/posts/clocks/station_clock.svg) no-repeat center; | |
background-size: 95%; | |
box-shadow: 0 0 0.5em rgba(0,0,0,0.2) inset; | |
} | |
.clock.station .seconds::before { | |
background: red; | |
border-radius: 50%; | |
content: ""; | |
position: absolute; | |
top: -9%; | |
left: -200%; | |
height: 18%; | |
width: 500%; | |
} | |
.clock.ios7 { | |
background: #fff url(/assets/images/posts/clocks/ios_clock.svg) no-repeat center; | |
background-size: 88%; | |
} | |
.clock.ios7:before { | |
background: black; | |
border-radius: 50%; | |
content: ""; | |
position: absolute; | |
left: 50%; | |
top: 50%; | |
transform: translate(-50%, -50%); | |
width: 6%; | |
height: 6%; | |
z-index: 0; | |
} | |
.clock.ios7:after { | |
width: 2%; | |
height: 2%; | |
} | |
.clock.ios7 .seconds { | |
border-radius: 200%/10%; | |
height: 30%; | |
left: 49.5%; | |
top: 20%; | |
width: 1%; | |
transform-origin: 50% 100%; | |
} | |
.clock.ios7 .minutes { | |
border-radius: 150%/10%; | |
width: 2%; | |
height: 35%; | |
left: 49%; | |
top: 15%; | |
transform-origin: 50% 100%; | |
} | |
.clock.ios7 .hours { | |
border-radius: 85%/10%; | |
width: 2%; | |
height: 20%; | |
left: 49%; | |
top: 30%; | |
transform-origin: 50% 100%; | |
} | |
.clock.simple { | |
background: #fff url(/assets/images/posts/clocks/ios_clock.svg) no-repeat center; | |
background-size: 88%; | |
} | |
.clock.simple:after { | |
background-color: #000; | |
width: 5%; | |
height: 5%; | |
} | |
.clock.simple .seconds { | |
background-color: #000; | |
height: 45%; | |
left: 49.5%; | |
top: 14%; | |
width: 1%; | |
transform-origin: 50% 80%; | |
} | |
.clock.simple .minutes { | |
width: 2%; | |
height: 40%; | |
left: 49%; | |
top: 10%; | |
transform-origin: 50% 100%; | |
} | |
.clock.simple .hours { | |
width: 2.5%; | |
height: 20%; | |
left: 48.75%; | |
top: 30%; | |
transform-origin: 50% 100%; | |
} | |
.hours.angled { | |
transform: rotateZ(-40deg); | |
} | |
.minutes.angled { | |
transform: rotateZ(40deg); | |
} |
See more on http://cssanimation.rocks
Forked from Donovan Hutchinson's Pen Basic animated clock.