Vyacheslav Palamar
Vyacheslav Palamar

Reputation: 507

CSS animation is slowing down when I use JS

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.

Upvotes: 2

Views: 398

Answers (3)

sglazkov
sglazkov

Reputation: 1066

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;
}

Upvotes: 0

grabantot
grabantot

Reputation: 2149

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/

Upvotes: 0

dewd
dewd

Reputation: 4429

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/

Upvotes: 1

Related Questions