Students Save 30%! Learn & create with unlimited courses & creative assets Students Save 30%! Save Now
Advertisement
  1. Web Design
  2. UI Design
Webdesign

Создание горизонтальной шкалы времени с помощью CSS и JavaScript

by
Difficulty:IntermediateLength:LongLanguages:

Russian (Pусский) translation by Anton Lisovsky (you can also view the original English article)

В предыдущей статье, я показал как сделать адаптивную вертикальную шкалу времени с нуля. Сегодня, я разберу процесс создания ассоциативной горизонтальной временной шкалы.

Как обычно, чтобы представить, что мы будем разрабатывать, ознакомьтесь с демонстрацией на CodePen (для более глубокого понимания концепции, взгляните на полную версию)

Нам предстоит многое разобрать, давайте же начнём!

1. HTML разметка

Размета аналогична разметке, которую мы использовали для вертикальной временной шкалы, разве что изменились три небольших детали:

  • Мы используем упорядоченный список вместо неупорядоченного, так как данный список семантически вернее.
  • В списке есть дополнительный элемент списка (последний), который в свою очередь будет пустым. В дальнейшем мы обсудим зачем это нужно.
  • Присутствует вспомогательный элемент (.arrows), который отвечает за навигацию.

Ниже пример необходимой нам разметки:

Начальное состояние временной шкалы выглядит следующим образом:

2. Добавляем первые CSS стили

После добавления основных стилей шрифтов, цвета, и так далее. Которые я не описал здесь, чтобы не усложнять, мы укажем основные CSS правила для создания структуры.

Важно - стоит обратить внимание на две вещи:

  • Мы добавили большой верхний и нижний padding нашему списку. Опять же, далее я объясню зачем это сделано.
  • Как вы наверно заметите в следующем примере, мы не можем видеть все элементы списка, так как ему задана ширина width: 100vw, а родитель обладает свойством overflow-x: hidden. Данный подход эффективно скрывает элементы списка. Благодаря навигации, однако, мы сможем управлять, перемещать эти элементы.

Зная это, ниже пример текущего состояния, внешнего вида нашей шкалы времени (без какого-либо контента, для простоты):

3. Стили элемента шкалы времени

На этом этапе мы добавим стили элементу div (будем называть их "элементы шкалы времени"), которые представляют из себя часть элемента списка, также как и псевдоэлемент ::before.

В дополнение, мы прибегнем к помощи :nth-child(odd) и :nth-child(even) CSS псевдоклассов.

Ниже основные стили для элементов временной шкалы:

Далее некоторые стили для чётных:

И наконец некоторые стили для нечётных:

Теперь можно ознакомиться с новым внешним видом временной шкалы, после добавления контента:

Как вы вероятно заметили, элементы шкалы времени абсолютно позиционированы. Зная это, можно убедиться, что вся шкала появляется, нам нужно задать большое верхнее и нижнее значения padding для списка. Если не добавить padding'и, шкала времени будет обрезаться:

How the timeline looks like without paddings

4. Стили навигации шкалы времени

Теперь пришёл черёд задать стили навигационным кнопкам. Помните, что по умолчанию мы отключили стрелку отвечающую за обратную прокрутку и присвоили ей класс disabled.

Вот стили, которые отвечают за всё это:

Правила выше, изменят внешний вид шкалы следующим образом:

5. Добавим интерактив

Основная структура временной шкалы готова. Добавим больше интерактивности.

Переменные

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

Инициализация

Когда все необходимые для страницы ресурсы будут готовы, вызовем функцию init.

Данная функция вызывает 4-и подфункции:

Как вы скоро поймёте, каждая функция служит определённой задаче.

Элементы временной шкалы, одинаковой высоты

Если вернуться к предыдущему примеру, вы заметите, что элементы шкалы времени различаются по высоте. Это не препятствует основному функционалу временной шкалы, однако скорее всего хочется, чтобы они были одинаковой высоты. Добиться этого можно, либо указав фиксированную высоту в CSS (простое решение), или динамично вычислять необходимую высоту, согласно самому большому элементу с помощью JavaScript.

Второй вариант более гибкий и стабильный, так что представляю вам функцию, которая позволяет добиться подобного поведения.

Эта функция находит высоту самого высокого элемента временной шкалы и задаёт её в качестве высоты по умолчанию для остальных элементов.

Результат представлен ниже:

6. Анимация временной шкалы

Теперь давайте сосредаточимся на анимации. Создадим для этого функцию, добавляющую данное поведение.

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

Каждый раз когда кнопка была нажата, мы определяем находится ли кнопка в нерабочем состоянии (disable), если это не так, мы отключим их. Это позволит нам убедиться, что кнопка была нажата один раз, до того как закончится анимация.

Код обработчика содержит нижеописанные строки кода:

Дальше нам предстоит:

  • Проверить первый раз была нажата кнопка. Опять же, вспомните, что кнопка обратной прокрутки (previous) по умолчанию не работает, так что единственная кнопка, которая может быть изначально нажата это - next
  • Первый раз мы используем свойство transform, для перемещения вправо на 280px. Значение переменной xScrolling определяет количество пикселей, на которые мы сместимся. 
  • С другой стороны, если мы уже нажали на кнопку, мы получаем текущее значение transform шкалы и добавляем или вычитаем данное значение, необходимое количество пикселей для перемещения (280px). Таким образом, как только мы нажали на кнопку previous, значение transform уменьшается и шкала будет прокручена слева направо.  Однако, когда кнопка next будет нажат, значение свойства transform уменьшается и шкала времени передвинется справа налево.

Код, отвечающий за подобный функционал:

Отличная работа! Мы только что добавили анимацию нашей временной шкале. Следующее испытание - выяснить когда анимации следует остановиться. Мы будем применять следующий подход:

  • Когда первый элемент временной шкалы становится полностью видимым, это значит, что мы уже достигли начала временной шкалы, в связи с этим мы отключаем кнопку previous. Также этот момент даёт нам понять, что кнопка next включена.
  • Когда последний элемент полостью видимй, это значит мы достигли конца шкалы времени, следовательно стоит отключить кнопку next. Кроме этого нужно включить кнопку previous.

Необходимо помнить - ширина последнего элемента равна ширине временной шкалы (280px). Мы задаём ему такое значение (или значение больше) так как нужно убедиться, что последний элемент будет виден до того как кнопка next будет выключена.

Чтобы определить, что целевой элемент полностью видим в текущей области видимости, мы воспользуемся тем же самым кодом, который использовали для создания вертикальной шкалы. Нужный код, ознакомиться с котором можно в одном из обсуждений на Stack Overflow, выглядит следующим образом:

Помимо кода описанного выше, понадобиться ещё один вспомогательный функционал:

Данная функция убирает класс disabled у элемента в зависимости от значения в параметре flag. Дополнительно, функция может изменить состояние disabled для этого элемента.

Принимая во внимание описанное выше, посмотрим на код, отвечающий за момент когда анимация должна прекратиться:

Также стоит обратить внимание на задержку в 1.1 секунды перед тем как код начнёт выполняться. Зачем это нужно?

Если вернуться и изучить наш CSS, вы увидите данное правило:

Тем самым анимации временной шкалы требуется одна секунда до завершения. Как только она завершится, мы ждём 100 миллисекунд, после чего выполняем наши проверки.

Ниже пример временной шкалы с анимацией:

7. Добавляем прокрутку

До этого момента, временная шкала никоим образом не реагировала на touch события. Тем не менее стоит добавить подобный функционал. Для этого мы можем написать собственную JavaScript реализацию, или использовать готовые библиотеки (к примеру Hammer.js, TouchSwipe.js).

Для нашего демо, мы не будем усложнять и прибегнем к помощи Hammer.js, для начала, добавим эту библиотеку в наш пример на CodePen:

How to include Hammerjs in our pen

Затем опишем соответствующую функцию:

Внутри функции выше, мы делаем следующее:

  • Создаём экземпляр Hammer.
  • Описываем обработчики событий swipeleft и swiperight.
  • Когда мы прокручиваем временную шкалу влево, мы вызываем нажатие на кнопку next, таким образом временная шкала будет прокручивается с анимацией справа налево.
  • Когда мы прокручиваем шкалу времени вправо, будет вызвано нажатие на кнопку previous, таким образом шкала прокручивается с анимацией слева направо.

Временная шкала с поддержкой прокрутки на мобильных и так далее:

Добавляем навигацию клавиатурой

Давайте и дальше улучшим впечатления пользователей, предоставив поддержку навигации клавиатурой. Наши задачи:

  • Когда будут нажаты кнопки на клавиатуре - стрелка влево или стрелка вправо, документ должен прокручиваться до конечной позиции временной шкалы (в случае если другая секция страницы в данный момент видна). Тем самым мы будем знать, что вся шкала времени видна.
  • Когда нажимаем кнопку со стрелкой влево, временная шкала должна анимироваться слева направо.
  • Точно также когда кнопка со стрелкой вправо будет нажата, шкала времени прокручивается с анимацией справа налево.

Вот пример соответствующей функции:

Шкала времени с поддержкой клавиатуры:

8. Добавляем адаптивность

Мы практически закончили! Последнее но не менее важное, давайте сделаем нашу шкалу времени адаптивной. Когда область видимости будет меньше 600px, будет отображаться следующая структура, расположенных друг под другом элементов:

Так как мы руководствуемся подходом сначала персональные компьютеры, ниже можно увидеть пример CSS правил, которые следует переписать:

Обратите внимание: для двух правил, которые представлены выше, нам приходится использовать !important для изменения стилей присвоенных в разметке JavaScript'ом.

Конечное состояние нашей временной шкалы:

Поддержка браузеров

Данный пример отлично работает во всех современных браузерах. Также, как вы вероятно заметили, мы использовали Babel для компиляции нашего ES6 кода в ES5.

Единственная небольшая проблема, которую я обнаружил, отображение текста меняется, это связанно с тем, что шкала времени анимированна. Я пробовал различные подходы, которые мне довелось найти на Stack Overflow, но так и не нашёл простого решения, которое будет работать на всех операционных системах, во всех браузерах. Так что помните о присутствие небольших проблем с отображением шрифта, в момент когда включается анимация нашей шкалы времени.

Заключение

В этом довольно подробном туториале, мы начали с создания обычного упорядоченного списка и в итоге сделали адаптивную горизонтальную временную шкалу. Без сомнения, мы рассмотрели много интересных вещей, но я надеюсь, вам понравилось и вы довольны окончательным результатом, кроме этого получили ценные знания.

Если у вас есть вопросы или если какие-то моменты для вас непонятны, оставьте комментарий снизу!

Дальнейшие шаги

В случае если вы хотите и дальше улучшить уже созданную временную шкалу, вот несколько вещей, который можно сделать:

  • Добавьте поддержку перетаскивания dragging. Вместо того, чтобы нажимать на кнопки временной шкалы для навигации, мы можем просто перетащить область временной шкалы. Для этого можно воспользоваться нативным Drag and Drop Api (которое к сожалению не поддерживает мобильные устройства, на момент написания данной статьи) или используйте стороннюю библиотеку на подобии Draggable.js.
  • Улучшите поведение временной шкалы, когда мы меняем размер окна браузера. К примеру, когда мы меняем размер области видимости, кнопки должны быть соответствующим образом включаться и выключаться.
  • Организуйте код другим образом, так чтобы им было удобнее управлять. Возможно, следует использовать распространённые шаблоны проектирования JavaScript.
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.