2

So, I try to make the animated watch, only using div elements. The problem is that the second hand gradually changes its speed when I use JavaScript to set the right angle for each hand. Without JavaScript animation works fine.

HTML:

<div class="rim">
 <div class="watch">
   <div class="index index-zero"></div>
   <div class="index index-one"></div>
   <div class="index index-two"></div>
   <div class="index index-three"></div>
   <div class="index index-four"></div>
   <div class="index index-five"></div>
   <div class="index index-six"></div>
   <div class="index index-seven"></div>
   <div class="index index-eight"></div>
   <div class="index index-nine"></div>
   <div class="index index-ten"></div>
   <div class="index index-eleven"></div>
   <div id="hours-hand" class="hours-hand-center">
     <div class="hours-hand">
     </div>
   </div>
   <div id="minutes-hand" class="minutes-hand-center">
     <div class="minutes-hand">
     </div>
   </div>
   <div id="seconds-hand" class="seconds-hand-center">
     <div class="seconds-hand">
     </div>
   </div>
 </div>

CSS:

.rim {
  width: 300px;
  height: 300px;
  top: 50%;
  left: 50%;
  position: absolute;
  border-radius: 50%;
  margin-left: -162px;
  margin-top: -162px;
  border: 12px solid #7f8c8d;
}

.watch {
  position: relative;
  width: 100%;
  height: 100%;
  background: #000000;
  border-radius: 50%;
}
.seconds-hand-center, .minutes-hand-center, .hours-hand-center {
  height: 20px;
  width: 20px;
  top: 50%;
  left: 50%;
  position: absolute;
  border-radius: 50%;
  margin-left: -10px;
  margin-top: -10px;
  background: #7f8c8d;
}

.seconds-hand-center {
  -webkit-animation:rotate 60s infinite;
  -moz-animation: rotate 60s infinite;
  animation: rotate 60s infinite;
}

.minutes-hand-center {
  -webkit-animation:rotate 3600s infinite steps(60);
  -moz-animation: rotate 3660s infinite steps(60);
  animation: rotate 3660s infinite steps(60);
}

.hours-hand-center {
  -webkit-animation:rotate 43200s infinite steps(60);
  -moz-animation: rotate 43200s infinite steps(60);
  animation: rotate 43200s infinite steps(60);
}

.seconds-hand, .minutes-hand, .hours-hand {
  position: absolute;
  background: #7f8c8d;
  height: 120px;
  width: 2px;
  top: 50%;
  left: 50%;
  margin-left: -1px;
}

.minutes-hand {
  width: 6px;
  height: 130px;
  margin-left: -3px;
}

.hours-hand {
  width: 10px;
  height: 70px;
  margin-left: -5px;
}


@-moz-keyframes rotate {
  100% {
    transform: rotateZ(360deg);
  }
}
@-webkit-keyframes rotate {
  100% {
    transform: rotateZ(360deg);
  }
}
@keyframes rotate {
  100% {
    transform: rotateZ(360deg);
  }
}

JavaScript:

var app = function app() {
  "use strict"
  var hoursHand = document.getElementById('hours-hand')
  var minutesHand = document.getElementById('minutes-hand')
  var secondsHand = document.getElementById('seconds-hand')
  var time = new Date()
  var hours = time.getHours()
  var minutes = time.getMinutes()
  var seconds = time.getSeconds()
  var secondsHandAngle = seconds * 6 + 180
  var minutesHandAngle = minutes * 6 + 180
  var hoursHandAngle = hours * 6 + minutes / 2 + 180

  secondsHandAngle = secondsHandAngle > 360 ?
    secondsHandAngle % 360 : secondsHandAngle

  minutesHandAngle = minutesHandAngle > 360 ?
    minutesHandAngle % 360 : minutesHandAngle

  hoursHandAngle = hoursHandAngle > 360 ?
    hoursHandAngle % 360 : hoursHandAngle

  hoursHand.setAttribute('style', 'transform: rotate(' +
  hoursHandAngle + 'deg);')
  minutesHand.setAttribute('style', 'transform: rotate(' +
  minutesHandAngle + 'deg);')
  secondsHand.setAttribute('style', 'transform: rotate(' +
  secondsHandAngle + 'deg);')

}

window.onload = app

Here is the fiddle.

4
  • probably you should set animation-timing-function: linear; for you animation. I'm trying to figure out where to put it. Commented Feb 20, 2016 at 15:16
  • Nope, it doesn't work :( Commented Feb 20, 2016 at 15:19
  • seems to work for me jsfiddle.net/q3axya9u/3 Commented Feb 20, 2016 at 15:28
  • idk, when I open it, the second hand is reeeaaally slow, it almost doesn't move. Commented Feb 20, 2016 at 15:33

3 Answers 3

1

Set an interval to change the time each second and remove the css which animates the hands.

setInterval(function(){app()},1000);

/*.seconds-hand-center {
  -webkit-animation:rotate 60s infinite;
  -moz-animation: rotate 60s infinite;
  animation: rotate 60s infinite;
}

.minutes-hand-center {
  -webkit-animation:rotate 3600s infinite steps(60);
  -moz-animation: rotate 3660s infinite steps(60);
  animation: rotate 3660s infinite steps(60);
}

.hours-hand-center {
  -webkit-animation:rotate 43200s infinite steps(60);
  -moz-animation: rotate 43200s infinite steps(60);
  animation: rotate 43200s infinite steps(60);
}*/`

See this fiddle:

https://jsfiddle.net/q3axya9u/2/

Sign up to request clarification or add additional context in comments.

3 Comments

Yeah, it works. But I really wanted to implement this animation using CSS. Still, thank you.
@VyacheslavPalamar css only won't be accurate because it has no concept of the current time. it will get out of sync with the real time within minutes or less. with javascript, you're rechecking the actual time each time the function is run. css animations and timeouts and intervals are best efforts - never exact.
Actually your JS way seems to be the most simple. I wouldn't say it is impossible with CSS + JS but it is getting a bit more complex because the minutes hand animation should start when the seconds hand is at 0 (and similarly for hours). If we try to do this with CSS animation-delay, the minutes hand always lags behind exactly by 1 minute (though it starts in correction position (like in this demo). So a +1 from me for your simple solution/
0

dewd suggests a good approach. You can modify it a bit to make it look cooler.

  hoursHand.setAttribute('style', 'transform: rotate(' +
  hoursHandAngle + 'deg); transition: all 1s; transition-timing-function: linear;')
  minutesHand.setAttribute('style', 'transform: rotate(' +
  minutesHandAngle + 'deg); transition: all 1s; transition-timing-function: linear;')
  secondsHand.setAttribute('style', 'transform: rotate(' +
  secondsHandAngle + 'deg); transition: all 1s; transition-timing-function: ease;')

https://jsfiddle.net/q3axya9u/5/

2 Comments

It looks really cool, but when the second hand reaches the 60 seconds, it does the flip move O_o
fixed it :) jsfiddle.net/q3axya9u/7 ...edit: Though there still seems to be some other problem
0

My solution here https://jsfiddle.net/serGlazkov/q3axya9u/6/

.seconds-hand-center>div {
  -webkit-animation:rotate 60s infinite linear;
  -moz-animation: rotate 60s infinite linear;
  animation: rotate 60s infinite linear;
}

.minutes-hand-center>div {
  -webkit-animation:rotate 3600s infinite steps(60) linear;
  -moz-animation: rotate 3660s infinite steps(60) linear;
  animation: rotate 3660s infinite steps(60) linear;
}

.hours-hand-center>div {
  -webkit-animation:rotate 43200s infinite steps(60) linear;
  -moz-animation: rotate 43200s infinite steps(60) linear;
  animation: rotate 43200s infinite steps(60) linear;
}

.seconds-hand, .minutes-hand, .hours-hand {
  position: absolute;
    top: 50%;
    left: 50%;
    width: 1px;
    height: 1px;
}
.seconds-hand::before, .minutes-hand::before, .hours-hand::before {
  content: "";
  position: absolute;
  background: #7f8c8d;
  top: 50%;
  left: 50%;
}
.seconds-hand::before{
  height: 120px;
  width: 2px;
  margin-left: -1px;
}
.minutes-hand::before {
  width: 6px;
  height: 130px;
  margin-left: -3px;
}

.hours-hand::before {
  width: 10px;
  height: 70px;
  margin-left: -5px;
}

4 Comments

Please, can you explain this "before" thing? I read about it, but did not really understand.
I create this pseudo element for don't break your html structure, i make demo without "::before" here jsfiddle.net/serGlazkov/q3axya9u/8
So, you've fixed that by selecting direct children of an element? I mean, using >div?
in this situation >div = "::before"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.