Переход секундной стрелки в аналоговых часах УСБ с сек==59 на 0

Я хочу иметь плавный переход секундной стрелки от сек==59 до сек==0.

Он идет хорошо от 0 до 59 секунд, но на sec == 59 он не идет вперед, а откатывается в 0 позицию. Я пытаюсь сделать плавный переход от 59 до 0 по часовой стрелке (то же самое для секундной, минутной и часовой стрелок). Вот полный код часов -

let secHand = document.querySelector(".sec-hand")
let minHand = document.querySelector(".min-hand")
let hourHand = document.querySelector(".hour-hand")
let hands = document.querySelectorAll(".hand")

function setTime() {
  const now = new Date();
  const sec = now.getSeconds();
  const secDegrees = ((sec / 60) * 360) + 90;
  secHand.style.transform = `rotate(${secDegrees}deg)`;

  const mint = now.getMinutes();
  const mintDegrees = ((mint / 60) * 360) + 90;
  minHand.style.transform = `rotate(${mintDegrees}deg)`;

  const hour = now.getHours();
  const hourDegrees = ((hour / 12) * 360) + 90;
  hourHand.style.transform = `rotate(${hourDegrees}deg)`;

  //console.info(`${hour} : ${mint} : ${sec}`)
}
setInterval(setTime, 1000)
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.clock {
  background: transparent;
  width: 400px;
  height: 400px;
  margin: auto;
  margin-top: 100px;
  border-radius: 50%;
  border: 20px solid blue;
  position: absolute;
  left: 200px;
}

.center-dot {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background: rgb(195, 4, 4);
  position: absolute;
  top: calc(50% - 25px);
  left: calc(50% - 25px);
  z-index: 5;
}

.hand {
  width: 45%;
  height: 10px;
  background: black;
  position: absolute;
  top: calc(50% - 5px);
  left: 5%;
  border-radius: 10px;
  transform-origin: right;
  transition: all 0.5s;
  transform: rotate(90deg)
}
<div class = "clock">
  <div class = "center-dot"></div>
  <div class = "hour-hand hand"></div>
  <div class = "min-hand hand"></div>
  <div class = "sec-hand hand"></div>
</div>

Я следил за видео об этом и в этом, репетитор упомянул два решения: сначала продолжался непрерывный подсчет после sec = 59 и не возвращался к sec = 0 (но мне это решение не понравилось). Во-вторых, был временно удален переход, когда на sec==59 через JS. Я не знаю, как это сделать. Я пробовал это в setTime(), но не сработало -

if (sec == 59) {
        hands[2].setAttribute("transition", "");
    }

Пожалуйста помоги. Спасибо!

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
4
0
84
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Возможно, вам придется сделать немного больше, чтобы сгладить переход, но настройка перехода, как вы пытались, — это CSS вещь, а не HTML attribute

let secHand = document.querySelector(".sec-hand")
let minHand = document.querySelector(".min-hand")
let hourHand = document.querySelector(".hour-hand")
let hands = document.querySelectorAll(".hand")

function setTime() {
  const now = new Date();
  const sec = now.getSeconds();
  if (sec === 59) {
    secHand.style.transition = "0.5s";
  } else {
    secHand.style.transition = "0s";
  }
  const secDegrees = ((sec / 60) * 360) + 90;
  secHand.style.transform = `rotate(${secDegrees}deg)`;

  const mint = now.getMinutes();
  const mintDegrees = ((mint / 60) * 360) + 90;
  minHand.style.transform = `rotate(${mintDegrees}deg)`;

  const hour = now.getHours();
  const hourDegrees = ((hour / 12) * 360) + 90;
  hourHand.style.transform = `rotate(${hourDegrees}deg)`;

  //console.info(`${hour} : ${mint} : ${sec}`)
}
setInterval(setTime, 1000)
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.clock {
  background: transparent;
  width: 400px;
  height: 400px;
  margin: auto;
  margin-top: 100px;
  border-radius: 50%;
  border: 20px solid blue;
  position: absolute;
  left: 200px;
}

.center-dot {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background: rgb(195, 4, 4);
  position: absolute;
  top: calc(50% - 25px);
  left: calc(50% - 25px);
  z-index: 5;
}

.hand {
  width: 45%;
  height: 10px;
  background: black;
  position: absolute;
  top: calc(50% - 5px);
  left: 5%;
  border-radius: 10px;
  transform-origin: right;
  transition: all 0.5s;
  transform: rotate(90deg)
}
<div class = "clock">
  <div class = "center-dot"></div>
  <div class = "hour-hand hand"></div>
  <div class = "min-hand hand"></div>
  <div class = "sec-hand hand"></div>
</div>

Спасибо! это реально работает. Узнал что-то новое сегодня благодаря этому ответу.

Sagar Mavai 28.10.2022 12:23

Нет проблем, просто не забудьте выполнить ту же логику для минут и часов.

Harrison 28.10.2022 12:39
Ответ принят как подходящий

нужна запись secCount, mintCount, hourCount

let secHand = document.querySelector('.sec-hand') ;
let minHand = document.querySelector('.min-hand') ;
let hourHand = document.querySelector('.hour-hand') ;
let hands = document.querySelectorAll('.hand');


const delay = async (n = 0) => new Promise((res) => setTimeout(res, n));

(async () => {
  let secCount = 0;
  let mintCount = 0;
  let hourCount = 0;
  for (;;) {
    const now = new Date();
    const sec = now.getSeconds();
    const mint = now.getMinutes();
    const hour = now.getHours();
    if (sec == 0) {
      secCount++;
      if (mint == 0) {
        mintCount++;
        if (hour == 0) {
          hourCount++;
        }
      }
    }
    const secDegrees = (sec / 60 + secCount) * 360 + 90;
    secHand.style.transform = `rotate(${secDegrees}deg)`;

    const mintDegrees = (mint / 60 + mintCount) * 360 + 90;
    minHand.style.transform = `rotate(${mintDegrees}deg)`;

    const hourDegrees = (hour / 12 + hourCount) * 360 + 90;
    hourHand.style.transform = `rotate(${hourDegrees}deg)`;
    await delay(1000);
  }
})();
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.clock {
  background: transparent;
  width: 400px;
  height: 400px;
  margin: auto;
  margin-top: 100px;
  border-radius: 50%;
  border: 20px solid blue;
  position: absolute;
  left: 200px;
}

.center-dot {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background: rgb(195, 4, 4);
  position: absolute;
  top: calc(50% - 25px);
  left: calc(50% - 25px);
  z-index: 5;
}

.hand {
  width: 45%;
  height: 10px;
  background: black;
  position: absolute;
  top: calc(50% - 5px);
  left: 5%;
  border-radius: 10px;
  transform-origin: right;
  transition: all 0.5s;
  transform: rotate(90deg)
}
<div class = "clock">
  <div class = "center-dot"></div>
  <div class = "hour-hand hand"></div>
  <div class = "min-hand hand"></div>
  <div class = "sec-hand hand"></div>
</div>

Именно так, как я хочу, но я не понимаю, как это работает, потому что я не знаком с async и promise. Мне нужно прочитать о них. Большое спасибо.

Sagar Mavai 28.10.2022 12:19

Не по теме: (почти) только CSS.

Вам нужно только один раз установить текущее время с помощью JS.

document.body.style.setProperty("--time", Math.floor(Date.now() / 1000  - new Date().getTimezoneOffset() * 60) % (60 * 60 * 24));
@keyframes turn {
  from {
    transform: rotate(90deg);
  }
  to {
    transform: rotate(450deg);
  }
}

.sec-hand {
  /*animation: turn 60s infinite steps(60);*/
  animation: turn 60s infinite linear;
  animation-delay: calc(var(--time) * -1s);
}

.min-hand {
  /*animation: turn 3600s infinite steps(60);*/
  animation: turn 3600s infinite linear;
  animation-delay: calc(var(--time) * -1s);
}

.hour-hand {
  /*animation: turn 43200s infinite steps(12);*/
  animation: turn 43200s infinite linear;
  animation-delay: calc(var(--time) * -1s);
}

Минус: отсутствие опций, касающихся функций смягчения. Вы можете сделать так, чтобы стрелки часов работали непрерывно или пошагово (раз в секунду/минуту/час), но между шагами нет пошагового выполнения с замедлением.

document.body.style.setProperty("--time", Math.floor(Date.now() / 1000  - new Date().getTimezoneOffset() * 60) % (60 * 60 * 24));
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.clock {
  background: transparent;
  width: 400px;
  height: 400px;
  margin: auto;
  margin-top: 100px;
  border-radius: 50%;
  border: 20px solid blue;
  position: absolute;
  left: 200px;
}

.center-dot {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background: rgb(195, 4, 4);
  position: absolute;
  top: calc(50% - 25px);
  left: calc(50% - 25px);
  z-index: 5;
}

.hand {
  width: 45%;
  height: 10px;
  background: black;
  position: absolute;
  top: calc(50% - 5px);
  left: 5%;
  border-radius: 10px;
  transform-origin: right;
}




@keyframes turn {
  from {
    transform: rotate(90deg)
  }
  to {
    transform: rotate(450deg)
  }
}

.sec-hand {
  --animation: turn 60s infinite steps(60);
  animation: turn 60s infinite linear;
  animation-delay: calc(var(--time) * -1s);
}

.min-hand {
  --animation: turn 3600s infinite steps(60);
  animation: turn 3600s infinite linear;
  animation-delay: calc(var(--time) * -1s);
}

.hour-hand {
  --animation: turn 43200s infinite steps(12);
  animation: turn 43200s infinite linear;
  animation-delay: calc(var(--time) * -1s);
}
<div class = "clock">
  <div class = "center-dot"></div>
  <div class = "hour-hand hand"></div>
  <div class = "min-hand hand"></div>
  <div class = "sec-hand hand"></div>
</div>

Спасибо! Мне очень нравится применять анимацию CSS, как это делали вы. Это действительно работает с упомянутым вами недостатком. Вы облегчили понимание.

Sagar Mavai 28.10.2022 12:28

Другие вопросы по теме