DevGang
Авторизоваться

Как создать пользовательский HTML5-видеоплеер с помощью TailwindCSS и JavaScript

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

По этой причине большинство современных веб-приложений и платформ, таких как Udemy, Netflix, YouTube и Amazon Prime, не поставляют своим пользователям встроенный HTML5-видеоплеер по умолчанию. Вместо этого они создают свои собственные версии с изящным пользовательским интерфейсом, чтобы сделать свои платформы более привлекательными и удобными для пользователей.

Если вам когда-нибудь было интересно, как этим компаниям и веб-платформам удается добиться таких успехов, то эта статья для вас.

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

Вы также узнаете, как создать всё это, используя только собственный Video API, предоставляемый JavaScript в браузере - никаких внешних библиотек или инструментов не требуется.

Необходимые условия

  • Фундаментальные знания HTML5 и CSS
  • Фундаментальные знания Tailwind CSS
  • Фундаментальные знания JavaScript (ES6)
  • Редактор кода на ваш выбор
  • Браузер, поддерживающий современные возможности JavaScript (например, Chrome или Mozilla Firefox)

Начало работы

В этой статье мы будем использовать Tailwind CSS в качестве инструмента стилизации для создания пользовательского пользовательского интерфейса видеоплеера. Мы также будем использовать JavaScript для создания функциональности элементов управления.

Обратите внимание, что использование Tailwind CSS необязательно, так как для этого подойдет любой инструмент стилизации, например SCSS, CSS, styled-components и так далее - все зависит от вас.

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

В этом руководстве мы сосредоточимся на конкретных функциях видеоплеера. Эти функции дадут возможность и идеи для создания дополнительного функционала. Мы рассмотрим следующие функции:

  • Воспроизведение и пауза
  • Перемотка вперёд и назад
  • Отключение и включение звука
  • Поиск видео
  • Навигация по клавиатуре (использование клавиши "пробел" для воспроизведения и паузы, а клавиши со стрелками - для перемотки вперед и назад).

Мы не будем рассматривать отзывчивый дизайн здесь, поскольку не будем фокусироваться на том, чтобы сделать видеоплеер мобильно отзывчивым. Это упущение должно стать для вас вызовом и возможностью для обучения.

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

Как настроить среду разработки

На начальном этапе необходимо создать эффективную среду разработки, чтобы обеспечить бесперебойную работу. Для этого мы будем использовать Vite.

Прежде чем перейти к следующей части этого раздела, убедитесь, что на вашем компьютере установлены NodeJS и NPM или Yarn, так как они необходимы для установки инструментов и беспрепятственной настройки среды разработки.

Как настроить проект с помощью Vite

Чтобы создать проект в Vite, откройте терминал и введите следующую команду:

yarn create vite

Vite поможет вам настроить и выбрать инструменты, подходящие для вашей среды разработки.

Первым шагом будет выбор имени проекта - вы можете выбрать любое имя, которое вам больше нравится. В этой статье я буду использовать "html5-video-player" в качестве имени проекта.

Вывод терминала после выполнения команды "yarn create vite"
Вывод терминала после выполнения команды "yarn create vite"

Следующий шаг - выбор фреймворка проекта. Этот проект будет написан на чистом JavaScript, поэтому выберите "Vanilla", а затем выберите "JavaScript" в следующем запросе.

Вывод терминала после ввода имени проекта с просьбой выбрать фреймворк для проекта
Вывод терминала после ввода имени проекта с просьбой выбрать фреймворк для проекта
Вывод терминала после выбора каркаса "Vanilla"
Вывод терминала после выбора каркаса "Vanilla"

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

Терминал выдаёт сообщение об успешной настройке среды
Терминал выдаёт сообщение об успешной настройке среды

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

cd html5-video-player

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

yarn

После установки зависимостей перейдем к следующему шагу, который включает в себя настройку Tailwind CSS в качестве инструмента для создания стилей. Этот процесс очень прост и похож на то, как мы настраивали Vite.

Откройте терминал и выполните следующие команды:

yarn add -D tailwindcss postcss autoprefixer

Это позволит установить Tailwind CSS, наш инструмент для создания стилей, а также PostCSS и Autoprefixer. Эти инструменты помогут Tailwind CSS эффективно работать в вашем проекте.

Следующая команда включает в себя настройку конфигурационных файлов для Tailwind CSS и PostCSS.

Снова откройте локальный терминал и введите следующую команду:

npx tailwindcss init
Создание файла конфигурации Tailwind CSS
Создание файла конфигурации Tailwind CSS

Как указано в командном сообщении, в корне папки проекта будет создан файл tailwind.config.js. Этот файл будет содержать конфигурацию стилей, включая настройки шрифтов, цветов, плагинов и прочего. Для получения более подробной информации обратитесь к документации TailwindCSS.

Откройте сгенерированный файл конфигурации Tailwind CSS в редакторе кода и внесите в него следующие правки:

/** @type {import('tailwindcss').Config} */
export default {
  content: ['./index.html'],
  theme: {
    extend: {},
  },
  plugins: [],
}

Здесь мы просто отредактировали ключ content, чтобы указать файл, из которого TailwindCSS должен читать классы Tailwind CSS. Этим файлом оказался файл index.html, в котором и будет происходить наша основная работа.

Далее вам нужно настроить PostCSS, у которого нет автоматической команды настройки, как у TailwindCSS. Поэтому вы должны создать файл конфигурации вручную. Перейдите в корневую папку проекта и создайте файл postcss.config.js.

После создания файла postcss.config.js просто скопируйте и вставьте в него предоставленный фрагмент кода.

export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};

Затем настройте файл style.css так, чтобы он использовал CSS по умолчанию Tailwind. Это избавит вас от утомительной работы по настройке CSS по умолчанию вручную.

Откройте файл style.css в редакторе кода, удалите его содержимое, а затем вставьте в него следующий фрагмент кода:

@tailwind base;
@tailwind components;
@tailwind utilities;

Удаление ненужных файлов и кода

Файлы, генерируемые Vite, служат в основном в качестве руководств по добавлению собственных файлов и эффективному использованию бандлера. Поэтому вы можете удалить большинство из них, так как они не нужны для этого проекта.

Ниже перечислены файлы, которые необходимо удалить из проекта:

  1. counter.js
  2. javascript.svg

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

Откройте файл main.js, расположенный в корне проекта, и удалите весь код в нем.

Затем перейдите к файлу index.html и удалите все его текущее содержимое. После этого скопируйте и вставьте в файл приведенный ниже фрагмент кода:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./style.css" />
    <title>HTML5 Custom Video Player</title>
  </head>
  <body>
    <h1 class="text-3xl font-bold underline text-red-800">Hello world!</h1>
    <script type="module" src="/main.js"></script>
  </body>
</html>

На этом вы закончили эту часть! Теперь ваша среда разработки настроена и готова к созданию вашего пользовательского HTML5-видеоплеера.

Чтобы убедиться, что среда настроена правильно, проверьте следующее:

  • Файлы и папки проекта должны иметь следующую структуру:
Настройка проекта завершена: Visual Studio Code отображает структуру проекта.
Настройка проекта завершена: Visual Studio Code отображает структуру проекта.
  • Откройте терминал и выполните следующую команду:
yarn dev

Это создаст сервер разработки, на котором будет размещена ваша веб-страница. Откройте URL-адрес, предоставленный Vite.

Запуск сервера разработки Vite с помощью команды "yarn dev"
Запуск сервера разработки Vite с помощью команды "yarn dev"

Открыв ссылку http://localhost:5173/, вы увидите следующее:

Начальный пользовательский интерфейс, отображаемый после выполнения команды "yarn dev"
Начальный пользовательский интерфейс, отображаемый после выполнения команды "yarn dev"

Поздравляем! Вы успешно завершили этот раздел, посвященный настройке среды разработки, которая позволит нам эффективно работать над созданием нашего пользовательского HTML5-видеоплеера.

Устранение неполадок: Если вы обнаружите, что ваша настройка работает не так, как ожидалось, не волнуйтесь. Просто удалите папку с проектом и повторите процесс. Возможно, вы пропустили какой-то шаг или некоторые инструменты были установлены неправильно. Также перепроверьте файлы конфигурации Tailwind CSS и PostCSS, чтобы убедиться, что они содержат правильный код, как показано выше.

Как создать индивидуальный пользовательский интерфейс с помощью Tailwind CSS

В этом разделе мы рассмотрим все стили, необходимые для создания пользовательского интерфейса HTML5-видеоплеера. Мы рассмотрим этот процесс шаг за шагом.

Во-первых, скопируйте и вставьте следующий тег ссылки в шапку HTML, над ссылкой на таблицу стилей:

<link
  href="https://fonts.googleapis.com/icon?family=Material+Icons"
  rel="stylesheet"
/>

Это позволит нам использовать иконки Materialize CSS, которые необходимы для стилизации наших кнопок в пользовательском интерфейсе.

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

Далее давайте сосредоточимся на стилизации элемента video в нашей разметке. Просто замените элемент body на приведенный ниже фрагмент кода:

<body class="bg-indigo-950 p-10">
  <div
    id="container"
    class="w-4/5 h-4/5 mx-auto rounded-lg overflow-hidden relative group"
  >
    <!-- VIDEO -->
    <figure>
      <video class="w-full">
        <source src="/your-video.mp4" />
      </video>
    </figure>
  </div>
  <script type="module" src="/main.js"></script>
</body>

Представленный фрагмент кода включает разметку и стилистику для элемента video, а также внешний div, выступающий в качестве контейнера для всего пользовательского интерфейса видеоплеера. Элемент video вложен в элемент figure.

Для элемента source укажите путь к видео, которое вы хотите воспроизвести. Вы можете найти видео в Интернете, скачать его и добавить в "публичный" каталог в папке проекта. Затем привяжите атрибут src элемента source к видеофайлу. Вы можете найти бесплатные видеоролики для скачивания здесь.

Далее давайте придадим стиль элементам управления, используя иконки Materialize CSS, которые вы связали в HTML. Поместите следующий фрагмент кода под элементом figure внутри элемента body.

<!-- CONTROLS -->
<div
  id="controls"
  class="opacity-0 p-5 absolute bottom-0 left-0 w-full transition-opacity duration-300 ease-linear group-hover:opacity-100"
>
  <!-- PROGRESS BAR -->
  <div id="progress-bar" class="h-1 w-full bg-white cursor-pointer mb-4">
    <div
      id="progress-indicator"
      class="h-full w-9 bg-indigo-800 transition-all duration-500 ease-in-out"
    ></div>
  </div>
  <div class="flex items-center justify-between">
    <div class="flex items-center justify-between">
      <!-- REWIND BUTTON -->
      <button
        id="rewind"
        class="transition-all duration-100 ease-linear hover:scale-125"
      >
        <i class="material-icons text-white text-3xl w-12">replay_10 </i>
      </button>

      <!-- PLAY BUTTON -->
      <button
        id="play-pause"
        class="transition-all duration-100 ease-linear hover:scale-125"
      >
        <i class="material-icons text-white text-5xl inline-block w-12"
          >play_arrow</i
        >
      </button>

      <!-- FAST FORWARD BUTTON -->
      <button
        id="fast-forward"
        class="transition-all duration-100 ease-linear hover:scale-125"
      >
        <i class="material-icons text-white text-3xl w-12">forward_10 </i>
      </button>
    </div>

    <div>
      <!-- VOLUME BUTTON -->
      <button
        id="volume"
        class="transition-all duration-100 ease-linear hover:scale-125"
      >
        <i class="material-icons text-white text-3xl">volume_up</i>
      </button>
    </div>
  </div>
</div>

Этот фрагмент кода определяет расположение и поведение элементов управления для видеоплеера. Он начинается с создания контейнера div (<div id="controls">), который содержит все элементы управления. Изначально контейнер невидим (opacity-0) и становится видимым с плавным переходом (transition-opacity duration-300 ease-linear), когда пользователь наводит на него курсор (group-hover:opacity-100).

Внутри контейнера находится индикатор прогресса (<div id="progress-bar">) для отслеживания хода воспроизведения видео. Он состоит из белой фоновой полосы (bg-white) с подвижным индикатором (<div id="progress-indicator">), окрашенным в цвет индиго (bg-indigo-800). Индикатор прогресса является отзывчивым и позволяет пользователям переходить к различным частям видео.

Под индикатором прогресса находятся кнопки управления различными функциями. Кнопки перемотки, воспроизведения/паузы и быстрой перемотки сгруппированы в гибком контейнере (<div class="flex items-center justify-between">). Каждая кнопка (<button>) стилизована так, чтобы при наведении на неё мыши она немного увеличивалась (hover:scale-125).

  • Кнопка перемотки (<button id="rewind">) содержит значок (<i class="material-icons text-white text-3xl w-12">replay_10</i>), обозначающий десятисекундную перемотку.
  • Кнопка воспроизведения/паузы (<button id="play-pause">) содержит значок (<i class="material-icons text-white text-5xl w-12">play_arrow</i>), переключающий состояния воспроизведения и паузы.
  • Кнопка перемотки вперед (<button id="fast-forward">) содержит значок (<i class="material-icons text-white text-3xl w-12">forward_10</i>), обозначающий десятисекундную перемотку.

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

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

Скопируйте и вставьте приведенный ниже фрагмент кода в ваш файл style.css, прямо под директивами Tailwind CSS:

@layer base {
  video::-webkit-media-controls {
    display: none;
  }

  video::-webkit-media-controls-play-button {
    display: none;
  }

  video::-webkit-media-controls-volume-slider {
    display: none;
  }

  video::-webkit-media-controls-mute-button {
    display: none;
  }

  video::-webkit-media-controls-timeline {
    display: none;
  }

  video::-webkit-media-controls-current-time-display {
    display: none;
  }
}

Этот блок кода используется для настройки внешнего вида и поведения стандартных элементов управления мультимедиа, предоставляемых браузерным движком WebKit (обычно используется в таких браузерах, как Safari и некоторые версии Google Chrome) для элемента <video>.

Каждое правило CSS в базовом блоке @layer нацелено на определенные части стандартных элементов управления мультимедиа и скрывает их от глаз, устанавливая свойство display в none. Вот описание каждого правила:

  1. video::-webkit-media-controls: Это правило нацелено на весь набор элементов управления мультимедиа для элемента <video> и полностью скрывает их. Скрыв элементы управления, вы сможете реализовать собственные пользовательские элементы управления с помощью JavaScript и CSS, обеспечив более адаптированный и последовательный пользовательский опыт в разных браузерах.
  2. video::-webkit-media-controls-play-button: Это правило нацелено на кнопку воспроизведения в стандартных элементах управления мультимедиа и скрывает ее. Мы можем захотеть скрыть кнопку воспроизведения, если используем собственный дизайн кнопки воспроизведения или управляем воспроизведением программно.
  3. video::-webkit-media-controls-volume-slider: Это правило нацелено на ползунок громкости в стандартных элементах управления мультимедиа и скрывает его. Подобно скрытию кнопки воспроизведения, вы можете скрыть ползунок громкости, если реализуете свой собственный пользовательский интерфейс управления громкостью.
  4. video::-webkit-media-controls-mute-button: Это правило нацелено на кнопку выключения звука в стандартных элементах управления мультимедиа и скрывает ее. Если у вас есть пользовательская кнопка выключения/включения звука или вы хотите управлять отключением звука программно, вы можете скрыть кнопку выключения звука по умолчанию.
  5. video::-webkit-media-controls-timeline: Это правило нацелено на линию времени (индикатор воспроизведения) в стандартных элементах управления мультимедиа и скрывает ее. Скрыв временную шкалу, вы можете реализовать собственную шкалу прогресса с пользовательским стилем и дополнительными функциями.
  6. video::-webkit-media-controls-current-time-display: Это правило нацелено на отображение текущего времени в стандартных элементах управления мультимедиа и скрывает его. Если вы реализуете собственный пользовательский интерфейс для отображения текущего времени воспроизведения, вы можете скрыть отображение по умолчанию.

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

Проверьте URL-адрес вашего локального хоста, чтобы увидеть настроенный пользовательский интерфейс, отображаемый следующим образом:

Настраиваемый пользовательский интерфейс видеоплеера без наведения мыши, элементы управления скрыты.
Настраиваемый пользовательский интерфейс видеоплеера без наведения мыши, элементы управления скрыты.

Однако при наведении курсора элементы управления исчезают, и пользовательский интерфейс отображается следующим образом:

Пользовательский пользовательский интерфейс видеоплеера с видимыми элементами управления при наведении мыши.
Пользовательский пользовательский интерфейс видеоплеера с видимыми элементами управления при наведении мыши.

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

Как реализовать функцию воспроизведения и паузы

Чтобы реализовать функцию воспроизведения и паузы в пользовательском видеоплеере HTML5, начните с выбора кнопок воспроизведения и паузы с помощью их соответствующих идентификаторов из разметки. Вы также можете выбрать элемент видео. Затем вы будете программно управлять воспроизведением с помощью Video API, предоставляемого JavaScript в браузере. Давайте приступим.

"use strict";

const playNpauseBtn = document.querySelector("#play-pause");
const video = document.querySelector("video");

Из приведённого выше фрагмента кода:

  • "use strict"; обеспечивает работу JavaScript в строгом режиме, выявляя распространенные ошибки кодирования.
  • const playNpauseBtn = document.querySelector("#play-pause"); выбирает кнопку воспроизведения/паузы из HTML, используя ее ID.
  • const video = document.querySelector("video"); выбирает элемент видео из HTML.

Далее создадим две функции:

  1. playNpauseFn: Эта функция будет управлять воспроизведением и приостановкой видео.
  2. updatePlayNPauseIcon: Эта функция обновляет иконки воспроизведения и паузы в зависимости от текущего состояния видео. Например, если видео воспроизводится, то будет показан значок паузы, и наоборот.

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

function playNpauseFn() {
  video.paused ? video.play() : video.pause();
}

function updatePlayNPauseIcon() {
  const icon = playNpauseBtn.querySelector("i");
  icon.textContent = "";

  icon.textContent = video.paused ? "play_arrow" : "paused";
}

Давайте разберемся, что происходит. Начиная с функции playNpauseFn, при её вызове проверяется текущее состояние видео с помощью метода paused, доступного в Video API. Если видео приостановлено, она воспроизводит его. В противном случае видео приостанавливается. Для этого используется тернарный оператор в JavaScript.

В качестве альтернативы вы можете переписать это с помощью оператора if/else, как показано ниже:

function playNpauseFn() {
  if (video.paused) {
    video.play();
  } else {
    video.paused();
  }
}

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

Теперь перейдем ко второй функции, updatePlayNPauseIcon. Эта функция обновляет иконки воспроизведения и паузы в зависимости от текущего состояния видео. Давайте рассмотрим, как она реализована.

Посмотрите на стилизацию иконок ниже:

<button
  id="play-pause"
  class="transition-all duration-100 ease-linear hover:scale-125"
>
  <i class="material-icons text-white text-5xl inline-block w-12">play_arrow</i>
</button>

Этот код создает кнопку с ID "воспроизведение-пауза", которая содержит значок, указанный тегом <i>. Materialize CSS использует текст "play_arrow" внутри тега <i>, чтобы отобразить соответствующий значок. Если вы измените текст внутри <i>, Materialize CSS соответствующим образом обновит значок.

Теперь давайте сосредоточимся на функции, ответственной за обновление значка. Рассмотрим ее ниже отдельно:

function updatePlayNPauseIcon() {
  const icon = playNpauseBtn.querySelector("i");
  icon.textContent = "";

  icon.textContent = video.paused ? "play_arrow" : "paused";
}

Эта функция, updatePlayNPauseIcon(), отвечает за обновление значка воспроизведения/паузы в зависимости от текущего состояния видео.

  1. Сначала она выбирает элемент значка внутри кнопки воспроизведения/паузы.
  2. Затем она удаляет всё существующее текстовое содержимое внутри значка.
  3. Наконец, она устанавливает текстовое содержимое значка на "play_arrow", если видео приостановлено, или приостанавливает видео, если оно воспроизводится в данный момент. Это динамически изменяет значок, отображаемый на кнопке, чтобы отразить текущее состояние воспроизведения.

Примечание: Способ программного обновления значков может варьироваться в зависимости от службы значков и её API. Эта конкретная реализация специфична для значков Materialize CSS.

Далее давайте подключим эти функции к событиям, которые их запускают. Давайте посмотрим, как это работает ниже:

video.addEventListener("play", updatePlayNPauseIcon);
video.addEventListener('click', playNpauseFn)
video.addEventListener("pause", updatePlayNPauseIcon);
playNpauseBtn.addEventListener("click", playNpauseFn);

В данном коде:

  • video.addEventListener("play", updatePlayNPauseIcon);: Эта строка добавляет слушателя событий к элементу video, специально прослушивая событие play. Когда видео начинает воспроизводиться, срабатывает функция updatePlayNPauseIcon, обновляя иконку воспроизведения/паузы соответствующим образом.
  • video.addEventListener('click', playNpauseFn): Эта строка добавляет к элементу video слушатель события click. Когда видео будет нажато, сработает функция playNpauseFn, которая воспроизведёт или поставит видео на паузу.
  • video.addEventListener("pause", updatePlayNPauseIcon);: Эта строка добавляет слушателя событий к элементу video, который прослушивает событие pause. Когда видео приостанавливается, он запускает функцию updatePlayNPauseIcon для обновления значка воспроизведения/паузы.
  • playNpauseBtn.addEventListener("click", playNpauseFn);: Эта строка добавляет слушателя событий к элементу кнопки воспроизведения/паузы. Когда кнопка нажимается, он запускает функцию playNpauseFn, которая воспроизводит или приостанавливает видео.

У нас есть четыре слушателя событий на двух выделенных элементах. Давайте разберем, что происходит:

  • Элемент video прослушивает событие play. Когда видео начинает воспроизводиться, срабатывает updatePlayNPauseIcon, обновляющий иконку в зависимости от текущего состояния видео.
  • Элемент video также прослушивает событие click. При нажатии он запускает функцию playNpauseFn, которая переключает воспроизведение и паузу видео.
  • Кроме того, элемент video прослушивает событие pause. Когда видео приостанавливается, срабатывает playNpauseFn, переключая состояние воспроизведения видео.
  • Элемент кнопки воспроизведения/паузы также прослушивает событие click. При нажатии он запускает playNpauseFn, переключаясь между воспроизведением и паузой видео.

На этом мы завершаем данный раздел. Теперь вы можете попробовать функцию воспроизведения и паузы. Видео должно эффективно приостанавливаться и воспроизводиться, а иконки корректно обновляться.

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

Тестирование функций воспроизведения и паузы
Тестирование функций воспроизведения и паузы

В следующем разделе мы реализуем функцию перемотки назад и вперед.

Как реализовать функции перемотки вперёд и назад

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

Для начала выделим соответствующие кнопки из HTML-документа, используя их идентификаторы, и сохраним их в переменных:

const rewindBtn = document.querySelector("#rewind");
const fastForwardBtn = document.querySelector("#fast-forward");

После этого необходимо создать функцию, отвечающую за перемотку и перемотку вперёд. Ниже приведен фрагмент кода:

function rewindNforwardFn(type) {
  video.currentTime += type === "rewind" ? -10 : 10;
}

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

  • Он принимает параметр под названием type, который указывает, хотите ли вы перемотать вперёд или назад.
  • Если type - "перемотка назад", то из текущего времени воспроизведения видео (video.currentTime) вычитается 10 секунд.
  • Если значение type не равно "перемотка назад" (что означает, что вы хотите перемотать видео вперед), оно добавляет 10 секунд к текущему времени воспроизведения видео. Это позволяет пользователям перемещаться по видео либо назад, либо вперед на 10-секундные интервалы, в зависимости от значения параметра type.

Далее необходимо подключить слушателей событий на кнопках для запуска функции rewindNforward.

rewindBtn.addEventListener("click", () => rewindNforwardFn("rewind"));
fastForwardBtn.addEventListener("click", () => rewindNforwardFn("forward"));

Этот код добавляет слушателей событий для кнопок обратной и прямой перемотки. При нажатии на кнопку обратной перемотки запускается функция rewindNforward с аргументом rewind, указывающим на то, что вы хотите перемотать видео назад.

Аналогично, при нажатии кнопки перемотки вперед запускается функция rewindNforward с аргументом forward, указывающим на то, что вы хотите перемотать видео вперед.

Не стесняйтесь протестировать его и посмотреть, как он работает в пользовательском интерфейсе (UI).

Тестирование функций перемотки назад и вперёд
Тестирование функций перемотки назад и вперёд

Как реализовать функцию включения и выключения звука

Чтобы добавить функции включения и выключения звука, выполните те же действия, что и для предыдущих функций.

Начнем с выбора кнопки громкости из HTML-документа с помощью метода querySelector:

const volumeBtn = document.querySelector("#volume");

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

function muteNunmuteFn() {
  video.muted = video.muted ? false : true;
}

function updateVolumeIcon() {
  const icon = volumeBtn.querySelector("i");
  icon.textContent = "";
  icon.textContent = video.muted ? "volume_off" : "volume_up";
}

Этот код состоит из двух функций:

  1. muteNunmuteFn(): Эта функция переключает состояние звука видео. Если видео в данный момент выключено, она отключает его. В противном случае видео выключается.
  2. updateVolumeIcon(): Эта функция обновляет значок громкости, отображаемый на кнопке громкости. Она очищает всё существующее содержимое значка, а затем устанавливает текст значка на "volume_off", если видео выключено, и "volume_up", если видео не выключено.

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

video.addEventListener("volumechange", updateVolumeIcon);
volumeBtn.addEventListener("click", muteNunmuteFn);

Этот код устанавливает две вещи:

  1. Он добавляет слушателя событий к элементу видео, прослушивая событие "изменение громкости". При наступлении этого события (то есть при изменении громкости) он запускает функцию updateVolumeIcon, чтобы соответствующим образом обновить значок громкости.
  2. Он добавляет слушателя событий для кнопки громкости. Когда кнопка громкости нажимается, она запускает функцию muteNunmuteFn, переключаясь между включением и выключением видео.

Подобно событиям play и pause, видео также имеет событие volumechange, срабатывающее при изменении состояния громкости или отключения звука. Вы настраиваете видео на прослушивание этого события, и когда оно происходит, слушатель события запускает функцию, чтобы соответствующим образом обновить значок громкости.

Тестирование функций включения и выключения звука
Тестирование функций включения и выключения звука

Как обновить индикатор прогресса видео

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

В настоящее время индикатор выполнения не перемещается по мере воспроизведения видео и изменения времени. Мы собираемся это исправить.

Для начала удалите стилистику фиксированной длины для полосы прогресса. Изначально она была добавлена для стилизации, но теперь в ней нет необходимости, так как вы будете динамически регулировать ширину с помощью JavaScript. Обновите класс с w-9 до w-0 в элементе div с id "progress-indicator".

<!-- PROGRESS BAR -->
<div id="progress-bar" class="h-1 w-full bg-white cursor-pointer mb-4">
  <div
    id="progress-indicator"
    class="h-full w-0 bg-indigo-800 transition-all duration-500 ease-in-out"
  ></div>
</div>

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

const progressIndicator = document.querySelector("#progress-indicator");

После того как индикатор прогресса выбран, ваша следующая задача - реализовать функцию, отвечающую за его обновление.

function updateProgress() {
  const progressPercentage = (video.currentTime / video.duration) * 100;

  progressIndicator.style.width = `${progressPercentage}%`;
}

В приведенном выше фрагменте кода функция updateProgress вычисляет процент прогресса видео, деля текущее время видео на его общую продолжительность, а затем умножая на 100. Этот процент используется для установки длины элемента индикатора прогресса, визуально отображающего, какая часть видео была просмотрена.

Давайте разберем эту функцию. В первой строке кода вы вычисляете процентное отношение текущего времени видео к его общей продолжительности. Для этого нужно разделить текущее время на общую продолжительность видео. Например, если видео длится 30 секунд, а текущее время составляет 3 секунды, то 3, деленное на 30, равно 0,1.

Затем умножьте десятичную дробь на 100, чтобы получить процент. Так, 0,1, умноженная на 100, равна 10. Это означает, что вы находитесь на 10 % в 30-секундном видео.

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

Далее давайте добавим слушатель событий, который запускает эту функцию. Смотрите фрагмент кода ниже:

video.addEventListener('timeupdate', updateProgress);

Подобно другим событиям в Video API, есть еще одно, которое называется timeupdate. Это событие срабатывает при изменении текущего времени (CurrentTime) видео. Таким образом, по мере обновления времени функция updateProgress автоматически выполняется при каждом срабатывании события, что приводит к соответствующему обновлению индикатора прогресса.

Тестирование функциональности прогресса во времени
Тестирование функциональности прогресса во времени

Как реализовать функциональность поиска

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

Давайте начнем с выбора элемента индикатора прогресса в объектной модели документа (DOM).

const progessBar = document.querySelector("#progress-bar");

Получив индикатор прогресса из DOM с помощью его ID, следующим шагом будет создание функции поиска. Реализацию можно найти в следующем фрагменте кода:

function seekingFn(e) {
  const updatedTime = (e.offsetX / progessBar.offsetWidth) * video.duration;

  video.currentTime = updatedTime;
}

Давайте разберем эту функцию и поймем, что происходит.

Функция seekingFn корректирует текущее время воспроизведения видео, основываясь на положении, в котором пользователь щелкнул мышью на индикаторе выполнения. Она вычисляет обновленное время, деля горизонтальное смещение клика относительно ширины индикатора прогресса на общую длину индикатора прогресса. Затем он умножает это значение на общую продолжительность видео. Наконец, он устанавливает текущее время видео на рассчитанное обновлённое время.

Затем добавьте слушатель событий:

let mouseIsDown = false;

progessBar.addEventListener("mousedown", () => (mouseIsDown = true));
progessBar.addEventListener("mouseup", () => (mouseIsDown = false));
progessBar.addEventListener("click", seekingFn);
progessBar.addEventListener("mousemove", (e) => mouseIsDown && seekingFn);

В приведенном выше фрагменте кода обрабатываются события от мыши на индикаторе прогресса для поиска функций:

  • mouseIsDown - переменная, которая отслеживает, нажата ли кнопка мыши.
  • Когда кнопка мыши нажата (событие mousedown), mouseIsDown устанавливается в true.
  • Когда кнопка мыши отпускается (событие mouseup), mouseIsDown устанавливается в false.
  • Когда индикатор прогресса нажимается (событие click), запускается функция seekingFn для поиска позиции нажатия.
  • Когда мышь перемещается по индикатору прогресса (событие mousemove), если значение mouseIsDown истинно, то есть кнопка мыши нажата, то срабатывает функция seekingFn, позволяющая осуществлять поиск при перетаскивании мыши.
Тестирование функциональности поиска
Тестирование функциональности поиска

Как добавить навигацию по клавиатуре для обеспечения удобства пользования

В настоящее время наш видеоплеер поддерживает такие устройства-указатели, как мыши и световые ручки. Но мы стремимся обеспечить доступность для пользователей, которые не имеют или не могут использовать такие устройства. Поэтому мы стремимся сделать наш пользовательский HTML5-видеоплеер удобным для использования без указки, используя вместо нее клавиатуру.

Использование пробела для воспроизведения и паузы

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

Ниже приведен фрагмент кода, демонстрирующий, как этого добиться:

window.addEventListener("keyup", (e) => {
  if (e.code === "Space") {
    playNpauseFn();
  }
});

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

Вот пошаговое объяснение кода:

  • window.addEventListener("keyup", (e) => { ... }):
  1. Вы добавляете слушателя событий к объекту окна.
  2. Этот слушатель срабатывает при отпускании клавиши (событие keyup).
  • (e) => { ... }:
  1. Это функция-стрелка, которая выполняется при наступлении события нажатия клавиши (keyup).
  2. Параметр e представляет объект события, содержащий информацию о событии.
  • if (e.code === "Space") { ... }:
  1. Это условие проверяет, является ли клавиша, которая была отпущена, пробелом.
  2. e.code содержит код клавиши, вызвавшей событие.
  • playNpauseFn();:
  1. Если отпущенная клавиша - пробел, вызывается эта функция.
  2. Функция playNpauseFn отвечает за переключение между воспроизведением и приостановкой видео.

Использование клавиш со стрелками для перемотки назад и вперёд

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

Основываясь на предыдущем фрагменте кода для функций воспроизведения и паузы, вы можете использовать клавиши со стрелками для перемотки видео.

window.addEventListener("keyup", (e) => {
  if (e.code === "Space") {
    playNpauseFn();
  } else if (e.code === "ArrowLeft") {
    rewindNforwardFn("rewind");
  } else if (e.code === "ArrowRight") {
    rewindNforwardFn("forward");
  } else {
    return;
  }
});

Этот фрагмент кода устанавливает на объекте окна слушатель событий для события keyup. Когда любая клавиша отпускается, запускается предоставленная функция обратного вызова с параметром события. Внутри функции обратного вызова есть условные операторы для проверки того, какая клавиша была нажата:

  • Если нажатой клавишей является пробел, выполняется функция playNpauseFn, переключающая воспроизведение и паузу видео.
  • Если нажатой клавишей является клавиша со стрелкой влево ("ArrowLeft"), вызывается функция rewindNforwardFn с аргументом "rewind", указывающим на то, что видео должно быть перемотано назад.
  • Если нажатой клавишей является клавиша со стрелкой вправо ("ArrowRight"), вызывается функция rewindNforwardFn с аргументом "forward", указывающим на то, что видео должно быть перемотано вперед.
  • Если нажатая клавиша не является пробелом, стрелкой влево или стрелкой вправо, функция возвращается, не выполнив никаких действий.

Как должен выглядеть ваш код

Мы закончили создание нашего собственного HTML5-видеоплеера. Поздравляем вас с тем, что вы научились этому.

Если вы столкнулись с какими-то трудностями или пропустили какие-то шаги, не волнуйтесь. Ниже вы можете найти фрагменты кода для каждого основного файла:

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link
      href="https://fonts.googleapis.com/icon?family=Material+Icons"
      rel="stylesheet"
    />
    <link rel="stylesheet" href="./style.css" />
    <title>HTML5 Custom Video Player</title>
  </head>
  <body class="bg-indigo-950 p-10">
    <div
      id="container"
      class="w-4/5 h-4/5 mx-auto rounded-lg overflow-hidden relative group"
    >
      <!-- VIDEO -->
      <figure>
        <video class="w-full">
          <source src="/oceans.mp4" />
        </video>
      </figure>

      <!-- CONTROLS -->
      <div
        id="controls"
        class="opacity-0 p-5 absolute bottom-0 left-0 w-full transition-opacity duration-300 ease-linear group-hover:opacity-100"
      >
        <!-- PROGRESS BAR -->
        <div id="progress-bar" class="h-1 w-full bg-white cursor-pointer mb-4">
          <div
            id="progress-indicator"
            class="h-full w-0 bg-indigo-800 transition-all duration-500 ease-in-out"
          ></div>
        </div>
        <div class="flex items-center justify-between">
          <div class="flex items-center justify-between">
            <!-- REWIND BUTTON -->
            <button
              id="rewind"
              class="transition-all duration-100 ease-linear hover:scale-125"
            >
              <i class="material-icons text-white text-3xl w-12">replay_10 </i>
            </button>

            <!-- PLAY BUTTON -->
            <button
              id="play-pause"
              class="transition-all duration-100 ease-linear hover:scale-125"
            >
              <i class="material-icons text-white text-5xl inline-block w-12"
                >play_arrow</i
              >
            </button>

            <!-- FAST FORWARD BUTTON -->
            <button
              id="fast-forward"
              class="transition-all duration-100 ease-linear hover:scale-125"
            >
              <i class="material-icons text-white text-3xl w-12">forward_10 </i>
            </button>
          </div>

          <div>
            <!-- VOLUME BUTTON -->
            <button
              id="volume"
              class="transition-all duration-100 ease-linear hover:scale-125"
            >
              <i class="material-icons text-white text-3xl">volume_up</i>
            </button>
          </div>
        </div>
      </div>
    </div>
    <script type="module" src="/main.js"></script>
  </body>
</html>

style.css

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  video::-webkit-media-controls {
    display: none;
  }

  video::-webkit-media-controls-play-button {
    display: none;
  }

  video::-webkit-media-controls-volume-slider {
    display: none;
  }

  video::-webkit-media-controls-mute-button {
    display: none;
  }

  video::-webkit-media-controls-timeline {
    display: none;
  }

  video::-webkit-media-controls-current-time-display {
    display: none;
  }
}

main.js

"use strict";

const playNpauseBtn = document.querySelector("#play-pause");
const video = document.querySelector("video");
const rewindBtn = document.querySelector("#rewind");
const fastForwardBtn = document.querySelector("#fast-forward");
const volumeBtn = document.querySelector("#volume");
const progressIndicator = document.querySelector("#progress-indicator");
const progessBar = document.querySelector("#progress-bar");

function playNpauseFn() {
  video.paused ? video.play() : video.pause();
}

function updatePlayNPauseIcon() {
  const icon = playNpauseBtn.querySelector("i");
  icon.textContent = "";

  icon.textContent = video.paused ? "play_arrow" : "paused";
}

function rewindNforwardFn(type) {
  video.currentTime += type === "rewind" ? -10 : 10;
}

function muteNunmuteFn() {
  video.muted = video.muted ? false : true;
}

function updateVolumeIcon() {
  const icon = volumeBtn.querySelector("i");
  icon.textContent = "";
  icon.textContent = video.muted ? "volume_off" : "volume_up";
}

function updateProgress() {
  const progressPercentage = (video.currentTime / video.duration) * 100;

  progressIndicator.style.width = `${progressPercentage}%`;
}

function seekingFn(e) {
  const updatedTime = (e.offsetX / progessBar.offsetWidth) * video.duration;

  video.currentTime = updatedTime;
}

// PLAY AND PAUSE FUNCTIONALITY
video.addEventListener("play", updatePlayNPauseIcon);
video.addEventListener("click", playNpauseFn);
video.addEventListener("pause", updatePlayNPauseIcon);
playNpauseBtn.addEventListener("click", playNpauseFn);

// REWIND AND FAST FORWARD
rewindBtn.addEventListener("click", () => rewindNforwardFn("rewind"));
fastForwardBtn.addEventListener("click", () => rewindNforwardFn("forward"));

// MUTE AND UNMUTE
video.addEventListener("volumechange", updateVolumeIcon);
volumeBtn.addEventListener("click", muteNunmuteFn);

// PROGRESS
video.addEventListener("timeupdate", updateProgress);

// SEEKING
let mouseIsDown = false;

progessBar.addEventListener("mousedown", () => (mouseIsDown = true));
progessBar.addEventListener("mouseup", () => (mouseIsDown = false));
progessBar.addEventListener("click", seekingFn);
progessBar.addEventListener("mousemove", (e) => mouseIsDown && seekingFn);

// KEYBOARD NAVIGATIONS
window.addEventListener("keyup", (e) => {
  if (e.code === "Space") {
    playNpauseFn();
  } else if (e.code === "ArrowLeft") {
    rewindNforwardFn("rewind");
  } else if (e.code === "ArrowRight") {
    rewindNforwardFn("forward");
  } else {
    return;
  }
});

Кроме того, вы можете найти весь код в репозитории GitHub, который я создал для этого проекта. Если он окажется полезным, поставьте репозиторию звезду - я буду вам очень признателен!

Получить доступ к живому сайту можно здесь.

Куда двигаться дальше

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

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

Продолжайте двигаться вперёд, и счастливого кодинга!

Заключение

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

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

Спасибо, что прочитали, и до встречи в следующий раз!

Источник:

#JavaScript #CSS #HTML
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу