#javascript #html #css #html5-audio
Вопрос:
У меня здесь есть переключатель, который работает без проблем.
https://jsfiddle.net/h4q86s25/
Я не могу заставить его работать с тем же кодом.
Во фрагменте, когда вы нажимаете на него, воспроизводится звук, кнопка меняется, но только один раз и не возвращается назад.
Как я могу вернуть кнопку назад и отключить звук?
https://jsfiddle.net/md4a0xyv/
(function iife() {
"use strict";
function show(el) {
el.classList.remove("hide");
}
function hide(el) {
el.classList.add("hide");
}
function getButtonContainer(el) {
while (el.classList.contains("playButton") === false) {
el = el.parentNode;
}
return el;
}
function hideAllButtons(button) {
const buttons = button.querySelectorAll(".play, .pause");
for (let i = 0; i < buttons.length; i ) {
hide(buttons[i]);
}
}
function getPlay(button) {
return button.querySelector(".play");
}
function getPause(button) {
return button.querySelector(".pause");
}
function showPlayButton(button) {
const play = getPlay(button);
hideAllButtons(button);
show(play);
button.classList.remove("active");
}
function isPlaying(button) {
const play = getPlay(button);
return play.classList.contains("active");
}
function pauseAllButtons() {
let buttons = document.querySelectorAll(".playButton");
for (let i = 0; i < buttons.length; i ) {
if (isPlaying(buttons[i])) {
showPlayButton(buttons[i]);
}
}
}
function showPauseButton(button) {
const pause = getPause(button);
pauseAllButtons();
hideAllButtons(button);
show(pause);
button.classList.add("active");
}
function getAudio() {
return document.querySelector("audio");
}
function playAudio(player, src) {
player.volume = 1.0;
if (player.getAttribute("src") !== src) {
player.setAttribute("src", src);
}
player.play();
}
function showButton(button, opts) {
if (opts.playing) {
showPlayButton(button);
} else {
showPauseButton(button);
}
}
function pauseAudio(player) {
player.pause();
}
function manageAudio(player, opts) {
if (opts.playing) {
pauseAudio(player);
} else {
playAudio(player, opts.src);
}
}
function togglePlayButton(button) {
const player = getAudio();
const playing = isPlaying(button);
showButton(button, {
playing
});
manageAudio(player, {
src: button.getAttribute("data-audio"),
playing
});
}
function playButtonClickHandler(evt) {
const button = getButtonContainer(evt.target);
togglePlayButton(button);
}
const playButton = document.querySelector(".wrapa");
playButton.addEventListener("click", playButtonClickHandler);
}());
.wrapa {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
background-color: black;
width: 150px;
height: 195px;
box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.2), 0 0 1px 2px black, inset 0 2px 2px -2px white, inset 0 0 2px 15px #47434c, inset 0 0 2px 22px black;
border-radius: 5px;
padding: 20px;
perspective: 700px;
}
.wrapa.active .play.pause.button {
transform: translateZ(20px) rotateX(25deg);
box-shadow: 0 -10px 20px #ff1818;
}
.wrapa.active .play.pause.button .light {
animation: flicker 0.2s infinite 0.3s;
}
.wrapa.active .play.pause.button .shine {
opacity: 1;
}
.wrapa.active .play.pause.button .shadow {
opacity: 0;
}
.wrapa .button {
transition: all 0.3s cubic-bezier(1, 0, 1, 1);
transform-origin: center center -20px;
transform: translateZ(20px) rotateX(-25deg);
transform-style: preserve-3d;
background-color: #9b0621;
width: 100%;
height: 100%;
position: relative;
cursor: pointer;
background: linear-gradient( #980000 0%, #6f0000 30%, #6f0000 70%, #980000 100%);
background-repeat: no-repeat;
}
.wrapa .button::before {
content: "";
background: linear-gradient( rgba(255, 255, 255, 0.8) 10%, rgba(255, 255, 255, 0.3) 30%, #650000 75%, #320000) 50% 50%/97% 97%, #b10000;
background-repeat: no-repeat;
width: 100%;
height: 50px;
transform-origin: top;
transform: rotateX(-90deg);
position: absolute;
top: 0;
}
.wrapa .button::after {
content: "";
background-image: linear-gradient(#650000, #320000);
width: 100%;
height: 50px;
transform-origin: top;
transform: translateY(50px) rotateX(-90deg);
position: absolute;
bottom: 0;
box-shadow: 0 50px 8px 0px black, 0 80px 20px 0px rgba(0, 0, 0, 0.5);
}
.wrapa .light {
opacity: 0;
animation: light-off 1s;
position: absolute;
width: 100%;
height: 100%;
background-image: radial-gradient(#ffc97e, #ff1818 40%, transparent 70%);
}
.wrapa .dots {
position: absolute;
width: 100%;
height: 100%;
background-image: radial-gradient(transparent 30%, rgba(101, 0, 0, 0.7) 70%);
background-size: 10px 10px;
}
.wrapa .characters {
position: absolute;
width: 100%;
height: 100%;
background: linear-gradient(white, white) 50% 20%/5% 20%, radial-gradient( circle, transparent 50%, white 52%, white 70%, transparent 72%) 50% 80%/33% 25%;
background-repeat: no-repeat;
}
.wrapa .shine {
transition: all 0.3s cubic-bezier(1, 0, 1, 1);
opacity: 0.3;
position: absolute;
width: 100%;
height: 100%;
background: linear-gradient(white, transparent 3%) 50% 50%/97% 97%, linear-gradient( rgba(255, 255, 255, 0.5), transparent 50%, transparent 80%, rgba(255, 255, 255, 0.5)) 50% 50%/97% 97%;
background-repeat: no-repeat;
}
.wrapa .shadow {
transition: all 0.3s cubic-bezier(1, 0, 1, 1);
opacity: 1;
position: absolute;
width: 100%;
height: 100%;
background: linear-gradient(transparent 70%, rgba(0, 0, 0, 0.8));
background-repeat: no-repeat;
}
@keyframes flicker {
0% {
opacity: 1;
}
80% {
opacity: 0.8;
}
100% {
opacity: 1;
}
}
@keyframes light-off {
0% {
opacity: 1;
}
80% {
opacity: 0;
}
}
<audio></audio>
<div class="playButton wrapa" data-audio="https://getradio.me/svoefm">
<div class="button play pause">
<div class="light"></div>
<div class="dots"></div>
<div class="characters"></div>
<div class="shine"></div>
<div class="shadow"></div>
</div>
</div>
Комментарии:
1. Селектор
.wrapa.active .play .pause .button .shine
вряд ли что-то общее, поскольку похоже, что элемент с классомplay
всегда(?) есть классpause
и класс,button
и что селектор находит все элементы с классомshine
, который имеет предка с классомbutton
, который сам по себе имеет предка с классомpause
, который сам по себе имеет предка с классомplay
, который сам по себе имеет предка с классамиwrapa
иactive
. Пространство-это селектор потомков. Объедините несколько классов в одном элементе без пробелов.2. Как бы я смог заставить его работать?
3. Кстати, эту функцию
getButtonContainer
можно было бы заменитьreturn el.closest('.playButton');
в современных браузерах.4. «Объедините несколько классов в одном элементе без пробелов». Так
.wrapa.active .play.pause.button .shine
что для этого конкретного селектора. Используйте логику, чтобы выяснить остальное.5. Там много кода, который был закомментирован. Мне кажется, что
showButton
функция должна обрабатывать состояние кнопки. Вы пытались добавить обратно закомментированные функции?
Ответ №1:
Ошибка в ваших getPause
getPlay
функциях и. Вы пытаетесь найти кнопку с .play
классом, но ваш контейнер содержит активное состояние, а не .play
кнопку. Если вы отредактируете эти две функции:
function getPlay(button) {
return button;
}
function getPause(button) {
return button;
}
Я думаю, что это должно работать, как и ожидалось.
ПРАВКА: Второе решение (упражнение). Вы также можете попытаться добавить активное состояние в .play
кнопку вместо контейнера. Затем вы должны изменить showPauseButton
и showPlayButton
.
Пример:
function showPauseButton(button) {
const pause = getPause(button);
pauseAllButtons();
hideAllButtons(button);
show(pause);
// button.classList.add("active");
pause.classList.add("active");
}
(function iife() {
"use strict";
function show(el) {
el.classList.remove("hide");
}
function hide(el) {
el.classList.add("hide");
}
function getButtonContainer(el) {
while (el.classList.contains("playButton") === false) {
el = el.parentNode;
}
return el;
}
function hideAllButtons(button) {
const buttons = button.querySelectorAll(".play, .pause");
for (let i = 0; i < buttons.length; i ) {
hide(buttons[i]);
}
}
function getPlay(button) {
return button;
}
function getPause(button) {
return button;
}
function showPlayButton(button) {
const play = getPlay(button);
hideAllButtons(button);
show(play);
button.classList.remove("active");
}
function isPlaying(button) {
const play = getPlay(button);
return play.classList.contains("active");
}
function pauseAllButtons() {
let buttons = document.querySelectorAll(".playButton");
for (let i = 0; i < buttons.length; i ) {
if (isPlaying(buttons[i])) {
showPlayButton(buttons[i]);
}
}
}
function showPauseButton(button) {
const pause = getPause(button);
pauseAllButtons();
hideAllButtons(button);
show(pause);
button.classList.add("active");
}
function getAudio() {
return document.querySelector("audio");
}
function playAudio(player, src) {
player.volume = 1.0;
if (player.getAttribute("src") !== src) {
player.setAttribute("src", src);
}
player.play();
}
function showButton(button, opts) {
if (opts.playing) {
showPlayButton(button);
} else {
showPauseButton(button);
}
}
function pauseAudio(player) {
player.pause();
}
function manageAudio(player, opts) {
if (opts.playing) {
pauseAudio(player);
} else {
playAudio(player, opts.src);
}
}
function togglePlayButton(button) {
const player = getAudio();
const playing = isPlaying(button);
showButton(button, {
playing
});
manageAudio(player, {
src: button.getAttribute("data-audio"),
playing
});
}
function playButtonClickHandler(evt) {
const button = getButtonContainer(evt.target);
togglePlayButton(button);
}
const playButton = document.querySelector(".wrapa");
playButton.addEventListener("click", playButtonClickHandler);
}());
.wrapa {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
background-color: black;
width: 150px;
height: 195px;
box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.2), 0 0 1px 2px black, inset 0 2px 2px -2px white, inset 0 0 2px 15px #47434c, inset 0 0 2px 22px black;
border-radius: 5px;
padding: 20px;
perspective: 700px;
}
.wrapa.active .play.pause.button {
transform: translateZ(20px) rotateX(25deg);
box-shadow: 0 -10px 20px #ff1818;
}
.wrapa.active .play.pause.button .light {
animation: flicker 0.2s infinite 0.3s;
}
.wrapa.active .play.pause.button .shine {
opacity: 1;
}
.wrapa.active .play.pause.button .shadow {
opacity: 0;
}
.wrapa .button {
transition: all 0.3s cubic-bezier(1, 0, 1, 1);
transform-origin: center center -20px;
transform: translateZ(20px) rotateX(-25deg);
transform-style: preserve-3d;
background-color: #9b0621;
width: 100%;
height: 100%;
position: relative;
cursor: pointer;
background: linear-gradient( #980000 0%, #6f0000 30%, #6f0000 70%, #980000 100%);
background-repeat: no-repeat;
}
.wrapa .button::before {
content: "";
background: linear-gradient( rgba(255, 255, 255, 0.8) 10%, rgba(255, 255, 255, 0.3) 30%, #650000 75%, #320000) 50% 50%/97% 97%, #b10000;
background-repeat: no-repeat;
width: 100%;
height: 50px;
transform-origin: top;
transform: rotateX(-90deg);
position: absolute;
top: 0;
}
.wrapa .button::after {
content: "";
background-image: linear-gradient(#650000, #320000);
width: 100%;
height: 50px;
transform-origin: top;
transform: translateY(50px) rotateX(-90deg);
position: absolute;
bottom: 0;
box-shadow: 0 50px 8px 0px black, 0 80px 20px 0px rgba(0, 0, 0, 0.5);
}
.wrapa .light {
opacity: 0;
animation: light-off 1s;
position: absolute;
width: 100%;
height: 100%;
background-image: radial-gradient(#ffc97e, #ff1818 40%, transparent 70%);
}
.wrapa .dots {
position: absolute;
width: 100%;
height: 100%;
background-image: radial-gradient(transparent 30%, rgba(101, 0, 0, 0.7) 70%);
background-size: 10px 10px;
}
.wrapa .characters {
position: absolute;
width: 100%;
height: 100%;
background: linear-gradient(white, white) 50% 20%/5% 20%, radial-gradient( circle, transparent 50%, white 52%, white 70%, transparent 72%) 50% 80%/33% 25%;
background-repeat: no-repeat;
}
.wrapa .shine {
transition: all 0.3s cubic-bezier(1, 0, 1, 1);
opacity: 0.3;
position: absolute;
width: 100%;
height: 100%;
background: linear-gradient(white, transparent 3%) 50% 50%/97% 97%, linear-gradient( rgba(255, 255, 255, 0.5), transparent 50%, transparent 80%, rgba(255, 255, 255, 0.5)) 50% 50%/97% 97%;
background-repeat: no-repeat;
}
.wrapa .shadow {
transition: all 0.3s cubic-bezier(1, 0, 1, 1);
opacity: 1;
position: absolute;
width: 100%;
height: 100%;
background: linear-gradient(transparent 70%, rgba(0, 0, 0, 0.8));
background-repeat: no-repeat;
}
@keyframes flicker {
0% {
opacity: 1;
}
80% {
opacity: 0.8;
}
100% {
opacity: 1;
}
}
@keyframes light-off {
0% {
opacity: 1;
}
80% {
opacity: 0;
}
}
<audio></audio>
<div class="playButton wrapa" data-audio="https://getradio.me/svoefm">
<div class="button play pause">
<div class="light"></div>
<div class="dots"></div>
<div class="characters"></div>
<div class="shine"></div>
<div class="shadow"></div>
</div>
</div>
Комментарии:
1. Требуется ли пауза воспроизведения только в html, а не в css? <div class=»кнопка воспроизведения паузы «> css удален. jsfiddle.net/mvrhjo9k
2. Вам это также нужно в css, если вы хотите, чтобы кнопка выглядела и вела себя одинаково визуально. Просто попробуйте удалить его из css и посмотрите, что произойдет.
3. Я заметил, что ты хранил
.button
в jsfiddle. Да, тогда.play.pause
это не нужно в css, так как у вас есть только один.button
элемент в иерархии.4. Возможно, я слишком поспешил предложить сделать это сейчас, когда присмотрелся поближе. Он все еще работает, но вам все еще нужно было отредактировать функции
getPlay()
andgetPause()
. Сначала я думал, что нам сойдет с рук только изменение того, где мы добавили и удалили.active
класс, но я ошибался. В оригинальном примере, по-видимому, было более одной кнопки. В любом случае, продолжайте в том же духе 🙂5. Тогда я добавил кнопку: button.classList.удалить(«активный»); //// button.classList.добавить(«активный»); jsfiddle.net/ac9q4nL5 И я только что заметил, что воспроизведение/пауза больше не нужны в html.