Построим: с помощью JavaScript - видеопроигрыватель HTML5
Первоначально опубликовано на сайте web-crunch.com 4 октября 2018 г.
Добро пожаловать в следующий выпуск моей серии статей «Построим: с помощью JavaScript». В этом руководстве вы узнаете, как создавать, настраивать видеопроигрыватель HTML5 и управлять им с помощью стандартного JavaScript.
Я буду использовать комбинацию HTML, CSS и JavaScript для выполнения этой задачи, которая немного сложнее, чем в предыдущих частях этой серии.
Первоначальную идею по манипулированию элементом HTML5 Video я получил от Wes Bos, который сделал очень похожий видеоурок в курсе JavaScript 30. Я настоятельно рекомендую пройти его курс, поскольку он учит вас современным советам и приемам для рабочего процесса JavaScript.
Большая заслуга в концепции и структуре кода принадлежит Уэсу. Я хотел попробовать сделать что-то подобное со своим чутьем. Я использовал разные стили, соглашения об именах и многое другое, чтобы добиться того, что вы видите на финальном CodePen.
Приступим к кодированию:
Самый первый шаг к размещению видеоэлемента на странице - это его визуализация с использованием тега newish video
.
HTML
Мой последний HTML
выглядит следующим образом:
<div class="player">
<video class="player-video" src="https://staging.coverr.co/s3/mp4/Down_by_the_River.mp4"></video>
<div class="player-controls">
<div class="progress">
<div class="filled-progress"></div>
</div>
<div class="ply-btn">
<button class="player-btn toggle-play" title="Toggle Play">
<svg class="" width="16" height="16" viewBox="0 0 16 16"><title>play</title><path d="M3 2l10 6-10 6z"></path></svg>
</button>
</div>
<div class="sliders">
<input type="range" name="volume" class="player-slider" min="0" max="1" step="0.05" value="1">
<input type="range" name="playbackRate" class="player-slider" min="0.5" max="2" step="0.1" value="1">
</div>
<button data-skip="-10" class="player-btn">« 10s</button>
<button data-skip="10" class="player-btn">10s »</button>
</div>
</div>
Нам нужны различные элементы управления для управления некоторыми частями API
элемента video
. В каждом элементе video
есть огромное количество свойств, которыми мы можем управлять с помощью JavaScript. Все, от громкости до скорости воспроизведения, можно настроить с помощью нескольких строк кода.
HTML
выше содержит
- содержащий
.player
div, который мы будем использовать для стилизации. - элемент
video
с указанным атрибутомsrc
.player-controls
div, в котором будут все элементы управления, которые мы хотим.play-btn
div для упаковки значков воспроизведения / паузы, которые мы будем использовать- ползунки диапазона ввода для управления громкостью и скоростью воспроизведения
- кнопки для перехода вперед и назад
Эти элементы управления и элементы могут показаться сложными, если подумать о необходимости манипулировать с помощью JavaScript, но большая часть логики в конечном итоге будет связана с взаимодействием с пользователем. Это означает, что наш JavaScript будет во многом полагаться на слушателей событий, чтобы делать все и вся.
CSS
Хотя я назвал его CSS
выше, на самом деле я буду использовать SCSS
для написания своих стилей. Чтобы написать что-то подобное, вам понадобится прекомпилятор. Загляните в codepen для скомпилированных стилей, если вам нужно.
$accent-color: #FFEC41;
body {
align-items: center;
background: #000046;
background: linear-gradient(to right, #1CB5E0, #000046);
display: flex;
height: 100vh;
justify-content: center;
margin: 0;
padding: 0;
}
.player {
max-width: 800px;
border: 6px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 0 25px rgba(0, 0, 0, 0.1), 0 3px 3px rgba(0, 0, 0, 0.1);
position: relative;
overflow: hidden;
&:hover {
.progress {
height: 10px;
}
.player-controls {
transform: translateY(0);
}
}
}
.player:-webkit-full-screen,
.player:fullscreen {
max-width: none;
width: 100%;
}
.play-btn {
flex: 1;
}
.player-video {
width: 100%;
display: block;
}
.player-btn {
background: none;
border: 0;
color: white;
text-align: center;
max-width: 60px;
padding: 5px 8px;
svg {
fill: #FFFFFF;
}
&:hover,
&:focus {
border-color: $accent-color;
background: rgba(255, 255, 255, .2);
}
}
.player-slider {
width: 10px;
height: 30px;
}
.player-controls {
align-items: center;
display: flex;
position: absolute;
bottom: 0;
width: 100%;
transform: translateY(100%) translateY(-5px);
transition: all 0.3s;
flex-wrap: wrap;
background: rgba(0, 0, 0, 0.3);
}
.player-controls > * {
flex: 1;
}
.progress {
position: relative;
display: flex;
flex: 10;
flex-basis: 100%;
height: 4px;
transition: height 0.3s;
background: rgba(0, 0, 0, 0.5);
}
.filled-progress {
width: 50%;
background: $accent-color;
flex: 0;
flex-basis: 50%;
}
.sliders {
max-width: 200px;
display: flex;
}
input[type=range] {
-webkit-appearance: none;
background: transparent;
width: 100%;
margin: 0 5px;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 8px;
cursor: pointer;
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0 0 1px rgba(13, 13, 13, 0);
background: rgba(255, 255, 255, 0.5);
border-radius: 10px;
border: 0.2px solid rgba(1, 1, 1, 0);
}
input[type=range]::-webkit-slider-thumb {
height: 15px;
width: 15px;
border-radius: 50px;
background: white;
cursor: pointer;
-webkit-appearance: none;
margin-top: -3.5px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: rgba(255, 255, 255, 0.8);
}
input[type=range]::-moz-range-track {
width: 100%;
height: 8px;
cursor: pointer;
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0 0 1px rgba(13, 13, 13, 0);
background: #ffffff;
border-radius: 10px;
border: 0.2px solid rgba(1, 1, 1, 0);
}
input[type=range]::-moz-range-thumb {
box-shadow: 0 0 3px rgba(0, 0, 0, 0), 0 0 1px rgba(13, 13, 13, 0);
height: 15px;
width: 15px;
border-radius: 50px;
background: white;
cursor: pointer;
}
Многие элементы управления браузером по умолчанию для кнопок, диапазонов ввода и многого другого просто уродливы. Этот код компенсирует это, а также устанавливает максимальную ширину нашего видео, чтобы оно оставалось по центру страницы. Не стесняйтесь здесь сходить с ума и писать свои собственные стили.
JavaScript
Наш JavaScript будет ориентирован на объектно-ориентированный подход. Это означает, что мы создадим множество маленьких функций, которые в основном делают одно. В совокупности они сделают видео полнофункциональным компонентом. По отдельности это упростит понимание того, что происходит, любому другому разработчику, который может увидеть код. Большинство итераций в самом видео вызываются прослушивателями событий (список для взаимодействия с пользователем). Мы напишем функции, которые делают что-то, когда фиксируются определенные действия. Заключительная логика здесь:
const player = document.querySelector('.player');
const video = player.querySelector('.player-video');
const progress = player.querySelector('.progress');
const progressFilled = player.querySelector('.filled-progress');
const toggle = player.querySelector('.toggle-play');
const skippers = player.querySelectorAll('[data-skip]');
const ranges = player.querySelectorAll('.player-slider');
// Logic
function togglePlay() {
const playState = video.paused ? 'play' : 'pause';
video[playState](); // Call play or paused method
}
function updateButton() {
const togglePlayBtn = document.querySelector('.toggle-play');
if(this.paused) {
togglePlayBtn.innerHTML = `<svg class="" width="16" height="16" viewBox="0 0 16 16"><title>play</title><path d="M3 2l10 6-10 6z"></path></svg>`;
} else {
togglePlayBtn.innerHTML = `<svg width="16" height="16" viewBox="0 0 16 16"><title>pause</title><path d="M2 2h5v12H2zm7 0h5v12H9z"></path></svg>`;
}
}
function skip() {
video.currentTime += parseFloat(this.dataset.skip);
}
function rangeUpdate() {
video[this.name] = this.value;
}
function progressUpdate() {
const percent = (video.currentTime / video.duration) * 100;
progressFilled.style.flexBasis = `${percent}%`;
}
function scrub(e) {
const scrubTime = (e.offsetX / progress.offsetWidth) * video.duration;
video.currentTime = scrubTime;
}
// Event listeners
video.addEventListener('click', togglePlay);
video.addEventListener('play', updateButton);
video.addEventListener('pause', updateButton);
video.addEventListener('timeupdate', progressUpdate);
toggle.addEventListener('click', togglePlay);
skippers.forEach(button => button.addEventListener('click', skip));
ranges.forEach(range => range.addEventListener('change', rangeUpdate));
ranges.forEach(range => range.addEventListener('mousemove', rangeUpdate));
let mousedown = false;
progress.addEventListener('click', scrub);
progress.addEventListener('mousemove', (e) => mousedown && scrub(e));
progress.addEventListener('mousedown', () => mousedown = true);
progress.addEventListener('mouseup', () => mousedown = false);
Как видите, количество слушателей событий, которые нам здесь нужны, становится довольно сложным, но, тем не менее, все работает довольно хорошо. Обязательно просмотрите видео, чтобы получить полный контекст. Письменные версии предназначены для контекстных целей, но также и для справки, если вы предпочитаете ссылаться на код напрямую, а не на код.
Большое спасибо за просмотр / чтение. Впереди еще много всего. Если вы новичок здесь, обязательно посмотрите другие видео из этой серии, перечисленные ниже:
Давайте строим: с помощью серии JavaScript
- Построим: с помощью JavaScript - выпадающие списки и адаптивные меню« Сделай сам »
- Построим: с JavaScript - панель вещания с файлами cookie
- Построим: с помощью JavaScript - Sticky Nav
- Построим: с помощью JavaScript - динамические вкладки
- Давайте построим: с помощью JavaScript - модальные окна
Первоначально опубликовано на сайте web-crunch.com 4 октября 2018 г.