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.