Создание аудиоплеера при помощи HTML5. Часть 2: прототипирование

Перевод статьи Making An Audio Player With HTML5, Part 2: Prototyping с сайта demosthenes.info, c разрешения автора — Дадли Стори.

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

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

Одно из преимуществ размещения своего контента на собственном сервере – это возможность настраивать всё, с ним связанное: вместо того, чтобы вынужденно обходиться UI для аудиофайлов из SoundCloud или встроенными элементами управления браузера, мы можем создать наш собственный плеер, используя специализированные HTML5-элементы, зная лишь немного JavaScript.

Исходные элементы

Первым делом давайте убедимся, что мы в принципе можем проиграть аудиофайл на странице. Здесь я использую Трек 24 из альбома Ghosts III группы NIN под лицензией Creative Commons:

<figure id="audioplayer">
<audio controls src="24-ghosts-III.mp3"id="audiotrack"></audio>
</figure>

Поскольку последние версии Firefox наряду с другими современными браузерами теперь поддерживают.mp3, здесь я использую только этот кодек. Я разместил элемент <audio> внутри <figure>, т.к. мы будем добавлять в него элементы управления вместе с текстовой расшифровкой.

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

Работа над постепенным улучшением

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

var audioPlayer = document.getElementById("audioplayer"),
audioTrack = document.getElementById("audiotrack"),
playButton = document.createElement("button");
playButton.type = "button";
audioPlayer.appendChild(playButton);
audioTrack.removeAttribute("controls");

Добавленный внизу HTML-страницы, этот скрипт фактически сокращает наш аудиоплеер до простого элемента <button>. Прямо сейчас кнопка проигрывания не содержит никакого текста внутри себя. Но мы планируем часто менять текст в элементах «button», поэтому будет правильно поместить этот скрипт в функцию:

function setText(el,text) {
el.innerHTML = text;
}

Теперь мы легко можем установить текст для любого HTML-элемента.

setText(playButton,"Play");

Далее нам нужно заставить кнопку реально что-то делать:

playButton.addEventListener("click", player);
function player() {
if (audioTrack.paused) {
setText(playButton,"Pause");
audioTrack.play();
} else {
setText(playButton,"Play");
audioTrack.pause();
}
}

Заметьте, что мы не пытаемся сделать отдельные функции для «play» и «stop», а мыслим в категориях действия кнопки.

Создание кнопки «Mute»

Также нам необходимо создать элементы управления для громкости звука. Самое простое – это сделать кнопку «Mute», которая использует шаблон, очень похожий на шаблон кнопки Play/Pause:

var muteButton = document.createElement("button");
setText(muteButton,"Mute");
muteButton.type = "button";
audioPlayer.appendChild(muteButton);
muteButton.addEventListener("click", muter);
function muter() {
if (audioTrack.volume == 0) {
setText(this,"Mute");
audioTrack.volume = 1;
} else {
setText(this,"Unmute");
audioTrack.volume = 0;
} }

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

Создание регулятора громкости

Далее нам нужен более точный регулятор громкости. Очевидный кандидат для этого элемента управления UI – элемент «range».

volumeSlider = document.createElement("input");
volumeSlider.type = "range";

Элементу «range» через JavaScript нужно установить множество атрибутов, что мы могли бы сделать тем же способом, которым я только что установил тип для нового поля… то, что мы делаем прототип, еще не значит, что нам нужно идти длинным путем. В идеале, как минимум часть нашего кода будет перенесена в финальную версию медиаплеера, так что мы должны искать эффективные способы написания нашего кода прямо сейчас.

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

function setAttributes(el, attrs) {
for(var key in attrs){
el.setAttribute(key, attrs[key]);
}
}

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

setAttributes(volumeSlider, { "type": "range", "min": "0", "max": "1", "step": "any", "value": "1" });

Заметьте, что минимальное и максимальное значение регулятора соответствуют значениям функции muter().

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

volumeSlider.addEventListener("input", function(){ audioTrack.volume = volumeSlider.value; });

Здесь мы сталкиваемся с первой серьёзной проблемой: с функциональной точки зрения, снижение громкости регулятора до 0 и нажатие на «Mute» – это одно и тоже, так что изменение состояния должно отображаться в кнопке. Как нам это сделать?

Синхронизация элементов управления

Моим решением будет абстрагироваться от кнопок и смотреть на любые изменения в громкости самого элемента <audio> :

audioTrack.addEventListener('volumechange', volumizer);
function volumizer() {
if (audioTrack.volume == 0) setText(muteButton,"Unmute"); }
else { setText(muteButton,"Mute"); }
}

Осталась ещё одна вещь, которую нужно исправить. Когда музыкальный трек заканчивается, музыка должна возвращаться к началу, а кнопка воспроизведения должна отображать «Play» вместо «Pause» или «Stop»:

audioTrack.addEventListener('ended', finish);
function finish() {
audioTrack.currentTime = 0;
setText(playButton,"Play");
}

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

function player() {
if (audioTrack.paused) {
setText(this, "Stop");
audioTrack.play();
} else {
setText(this,"Play");
audioTrack.pause();
}
}
function setText(el,text) {
el.innerHTML = text;
}
function finish() {
audioTrack.currentTime = 0;
setText(playButton,"Play");
}
function volumizer() {
if (audioTrack.volume == 0) { setText(muteButton,"Unmute"); }
else { setText(muteButton,"Mute"); }
}
function muter() {
if (audioTrack.volume == 0) {
audioTrack.volume = restoreValue;
volumeSlider.value = restoreValue;
} else {
audioTrack.volume = 0;
restoreValue = volumeSlider.value;
volumeSlider.value = 0;
}
}
function setAttributes(el, attrs) {
for(var key in attrs){
el.setAttribute(key, attrs[key]);
}
}
var audioPlayer = document.getElementById("audioplayer"),
audioTrack = document.getElementById("audiotrack"),
playButton = document.createElement("button"),
muteButton = document.createElement("button"),
volumeSlider = document.createElement("input");
setText(playButton, "Play");
setText(muteButton, "Mute");
setAttributes(playButton, { "type": "button" });
setAttributes(muteButton, { "type": "button" });
setAttributes(volumeSlider, { "type": "range", "min": "0", "max": "1", "step": "any", "value": "1" });
audioPlayer.appendChild(volumeSlider);
audioPlayer.appendChild(muteButton);
audioPlayer.appendChild(playButton);
audioTrack.removeAttribute("controls");
playButton.addEventListener("click", player, false);
muteButton.addEventListener("click", muter, false);
volumeSlider.addEventListener("input", function(){ audioTrack.volume = volumeSlider.value; }, false);
audioTrack.addEventListener('volumechange', volumizer, false);
audioTrack.addEventListener('ended', finish, false);

Примечание

Этот код предполагает, что, как только скрипт загрузился, все условия окажутся идеальными: что браузер поддерживает HTML5 и все функции API, которые мы использовали, и что аудиотрек загрузился тотчас же.. Но это не всегда так: например, Android 2 и ниже не поддерживает event.ended для аудио. Существуют способы обойти это и множество фолбеков, которые мы могли бы добавить, но я не буду уделять им внимание сегодня.

P.S. Это тоже может быть интересно:

2 Комментарии

  1. Gor

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

    1. Максим Усачев (Автор записи)

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

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