Аналоговые часы с темной темой

Создание интерактивных, «живых» элементов интерфейса — задача, которая с Vue.js превращается из сложной технической проблемы в увлекательный и логичный процесс. Реактивность, декларативная привязка данных и компонентный подход позволяют легко описывать сложное поведение, сосредотачиваясь на логике, а не на ручных манипуляциях с DOM. Идеальная иллюстрация этого — создание интерактивных часов, которые не только показывают точное время, но и мгновенно реагируют на действия пользователя, например, на смену темы. Именно такой компонент вы видите ниже.

Мы назвали этот компонент «Часы-переключатель», так как он сочетает в себе элегантные аналоговые часы, цифровое время, дату и кнопку переключения между светлой и темной темой — все в одном реактивном компоненте.

{{ calcHours }}:{{ calcMinutes }}
{{ date }} {{ month }}, {{ day }}

Внимание! Представленный код — это готовый компонент, но для его работы на странице должен быть установлен и подключен фреймворк Vue. Если вы начинающий разработчик, просто добавьте строку
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
в раздел <head> вашего HTML, и всё заработает.

Разбор кода компонента «Vue Часы-переключатель»

Давайте детально рассмотрим, как устроен этот компонент. Весь код можно условно разделить на три части: шаблон (HTML), стили (CSS) и логика (JavaScript на Vue 3 Composition API).

Шаблон (Template)

Шаблон построен на реактивной привязке данных Vue :class, :style, {{ }}.

  1. Переключение темы: Класс dark динамически добавляется к корневому блоку часов .app__clock и другим элементам в зависимости от значения themeToggle. Сама кнопка-переключатель .app__clock-btn меняет SVG-иконку (солнце/луна) на лету.
  2. Циферблат: 12 делений .line генерируются через v-for и поворачиваются на нужный угол с помощью :style.
  3. Стрелки: Часовой, минутной и секундной стрелкам .hour-hand, .minute-hand, .second-hand вычисляется угол поворота rotateZ на основе текущего времени. Функция scale преобразует единицы времени (часы, минуты, секунды) в градусы.
  4. Время и дата: Цифровое время calcHours:calcMinutes, дата и день недели отображаются через вычисляемые свойства и реактивные переменные.

Стили (CSS)

Стили используют современные возможности CSS:

  1. CSS-переменные (--tr): Задают единое время анимации для всех переходов.
  2. Класс .dark: Инвертирует цвета, меняя тему всей композиции.
  3. clamp(): Обеспечивает отзывчивую, плавную типографику, которая масштабируется между заданными пределами.
  4. Инлайн SVG: Иконки для кнопки темы встроены в CSS как фоновые изображения в формате Data URL, что исключает дополнительные HTTP-запросы.
  5. aspect-ratio: Гарантирует идеальную круглую форму центра циферблата.

Логика (Composition API)

Логика компонента использует Vue 3 Composition API (setup()):

  1. Реактивные переменные (ref): themeToggle, hours, minutes, seconds, date, month, day хранят текущее состояние.
  2. Вычисляемые свойства (computed): calcHours и calcMinutes форматируют время, добавляя ведущий ноль.
  3. Функция setTime: Извлекает текущие дату и время из объекта Date и обновляет реактивные переменные.
  4. Функция scale: Утилита для преобразования значения из одного числового диапазона в другой (например, 0-59 секунд в 0-360 градусов).
  5. Хук onMounted: Запускает первоначальную установку времени и задает интервал (setInterval) для его обновления каждую секунду, заставляя часы идти.

Таким образом: Vue.js берет на себя всю работу по синхронизации DOM с данными. При изменении seconds.value Vue автоматически пересчитывает стиль секундной стрелки и перерисовывает её в браузере. А изменение themeToggle.value мгновенно приводит к перерасчету всех привязанных классов и обновлению интерфейса.

От идеи до реализации: разрабатываем креативные и функциональные UI-компоненты

Наша веб-студия специализируется на создании современных, производительных и пользовательских интерфейсов. Мы можем разработать для вашего проекта аналогичный интерактивный элемент, сложную анимацию или целый фронтенд на Vue.js — от концепции до внедрения.

Свяжитесь с нами, чтобы обсудить ваш проект!