一个页面上的多个音频播放器,只有第一个播放器响应点击
Multiple Audio Players on one page, only first player responds to click
我从 this 文章中获取了音频播放器代码,进行了一些样式更改,现在正尝试在一个页面上显示多个此类播放器。目前,只有第一个玩家响应点击。
我使用行和列元素来显示整页行,每行 3 个播放器,每个播放器都有自己的图标图像和音频源文件。我现在的麻烦是建立索引搜索程序,以便在单击button_X时JS可以播放audio_X。
我已经在 Whosebug 上尝试了其他解决方案,但无济于事,所以我删除了我尝试过的所有更改,并从头开始。
const playerButton = document.querySelector('.player-button'),
audio = document.querySelector('audio'),
playIcon = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z" clip-rule="evenodd" />
</svg>
`,
pauseIcon = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd" />
</svg>
`;
function toggleAudio() {
if (audio.paused) {
audio.play();
playerButton.innerHTML = pauseIcon;
// document.getElementById("1").style.opacity = "1";
} else {
audio.pause();
playerButton.innerHTML = playIcon;
// document.getElementById("1").style.opacity = "0";
}
}
playerButton.addEventListener('click', toggleAudio);
function audioEnded() {
playerButton.innerHTML = playIcon;
}
audio.onended = audioEnded;
const timeline = document.querySelector('.timeline');
function changeTimelinePosition() {
const percentagePosition = (100 * audio.currentTime) / audio.duration;
timeline.style.backgroundSize = `${percentagePosition}% 100%`;
timeline.value = percentagePosition;
}
audio.ontimeupdate = changeTimelinePosition;
function changeSeek() {
const time = (timeline.value * audio.duration) / 100;
audio.currentTime = time;
}
timeline.addEventListener('change', changeSeek);
const soundButton = document.querySelector('.sound-button'),
soundIcon = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
<path fill-rule="evenodd" d="M9.383 3.076A1 1 0 0110 4v12a1 1 0 01-1.707.707L4.586 13H2a1 1 0 01-1-1V8a1 1 0 011-1h2.586l3.707-3.707a1 1 0 011.09-.217zM14.657 2.929a1 1 0 011.414 0A9.972 9.972 0 0119 10a9.972 9.972 0 01-2.929 7.071 1 1 0 01-1.414-1.414A7.971 7.971 0 0017 10c0-2.21-.894-4.208-2.343-5.657a1 1 0 010-1.414zm-2.829 2.828a1 1 0 011.415 0A5.983 5.983 0 0115 10a5.984 5.984 0 01-1.757 4.243 1 1 0 01-1.415-1.415A3.984 3.984 0 0013 10a3.983 3.983 0 00-1.172-2.828 1 1 0 010-1.415z" clip-rule="evenodd" />
</svg>`,
muteIcon = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
<path fill-rule="evenodd" d="M9.383 3.076A1 1 0 0110 4v12a1 1 0 01-1.707.707L4.586 13H2a1 1 0 01-1-1V8a1 1 0 011-1h2.586l3.707-3.707a1 1 0 011.09-.217zM12.293 7.293a1 1 0 011.414 0L15 8.586l1.293-1.293a1 1 0 111.414 1.414L16.414 10l1.293 1.293a1 1 0 01-1.414 1.414L15 11.414l-1.293 1.293a1 1 0 01-1.414-1.414L13.586 10l-1.293-1.293a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>`;
function toggleSound() {
audio.muted = !audio.muted;
soundButton.innerHTML = audio.muted ? muteIcon : soundIcon;
}
soundButton.addEventListener('click', toggleSound);
<div class="audio-player left">
<div class="icon-container">
<img src="coverart1.jpg" style="width: 100%" alt="">
<!--<svg xmlns="http://www.w3.org/2000/svg" class="audio-icon" viewBox="0 0 20 20" fill="currentColor">
<path d="blahblahblahpath" />
</svg>-->
<audio src="audio/1.mp3"></audio>
</div>
<div class="controls">
<button class="player-button">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
<path fill-rule="evenodd" d="blahblahblahpath" />
</svg>
</button>
<input type="range" class="timeline" max="100" value="0">
<button class="sound-button">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
<path fill-rule="evenodd" d="blahblahblahpath" clip-rule="evenodd" />
</svg>
</button>
</div>
</div>
有了这个结构,我不太确定如何为特定玩家index/search(除了知道我应该使用 queryselectALL 并为某些 JS 函数添加 for 循环之外)。
任何修复?目前第一个播放器运行良好,但没有其他播放器响应点击。也许与事件侦听器有关?
beyond knowing that i should probably use queryselectALL and add for loops to some JS functions
这就是重点:您需要为每个播放器实例分配事件侦听器。
let audioPlayers = document.querySelectorAll(".audio-player");
if (audioPlayers.length) {
audioPlayers.forEach(function(audioPlayer, i) {
let audio = audioPlayer.querySelector("audio");
let playerButton = audioPlayer.querySelector(".player-button");
playerButton.addEventListener("click", function(e) {
let current = e.currentTarget;
let audio = current.closest(".audio-player").querySelector("audio");
let btnSvg = current.querySelector(".useBtn");
if (!audio.paused) {
btnSvg.setAttribute("href", "#icon-play");
audio.pause();
} else {
btnSvg.setAttribute("href", "#icon-pause");
audio.play();
}
});
let timeline = audioPlayer.querySelector('.timeline');
timeline.addEventListener('change', function(e) {
let time = (timeline.value * audio.duration) / 100;
audio.currentTime = time;
});
audio.addEventListener('ended', function(e) {
console.log('audio finished');
timeline.value = 0;
});
audio.addEventListener('timeupdate', function(e) {
let percentagePosition = (100 * audio.currentTime) / audio.duration;
timeline.value = percentagePosition;
});
});
}
svg {
display: block;
width: 1em;
}
.player-button {
display: inline-block;
height: 1em;
background: none;
padding: 0;
border: none;
font-size: 1.2em;
position: relative;
bottom: -0.15em;
}
<div class="audio-player left">
<div class="icon-container">
<audio preload="metadata" src="https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3"></audio>
</div>
<div class="controls">
<button class="player-button">
<svg viewBox="0 0 20 20" fill="#3D3132">
<use class="useBtn" href="#icon-play" />
</svg>
</button>
<input type="range" class="timeline" min="0" max="100" step="1" value="0">
</div>
</div>
<div class="audio-player left">
<div class="icon-container">
<audio preload="metadata" src="https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3"></audio>
</div>
<div class="controls">
<button class="player-button">
<svg viewBox="0 0 20 20" fill="#3D3132">
<use class="useBtn" href="#icon-play" />
</svg>
</button>
<input type="range" class="timeline" min="0" max="100" step="1" value="0">
</div>
</div>
<svg class="plyrBtns" style="display:none" aria-hidden="true">
<symbol class="icon icon-play" id="icon-play" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z" clip-rule="evenodd" />
</symbol>
<symbol class="icon icon-pause" id="icon-pause" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd" />
</symbol>
</svg>
我从 this 文章中获取了音频播放器代码,进行了一些样式更改,现在正尝试在一个页面上显示多个此类播放器。目前,只有第一个玩家响应点击。
我使用行和列元素来显示整页行,每行 3 个播放器,每个播放器都有自己的图标图像和音频源文件。我现在的麻烦是建立索引搜索程序,以便在单击button_X时JS可以播放audio_X。
我已经在 Whosebug 上尝试了其他解决方案,但无济于事,所以我删除了我尝试过的所有更改,并从头开始。
const playerButton = document.querySelector('.player-button'),
audio = document.querySelector('audio'),
playIcon = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z" clip-rule="evenodd" />
</svg>
`,
pauseIcon = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd" />
</svg>
`;
function toggleAudio() {
if (audio.paused) {
audio.play();
playerButton.innerHTML = pauseIcon;
// document.getElementById("1").style.opacity = "1";
} else {
audio.pause();
playerButton.innerHTML = playIcon;
// document.getElementById("1").style.opacity = "0";
}
}
playerButton.addEventListener('click', toggleAudio);
function audioEnded() {
playerButton.innerHTML = playIcon;
}
audio.onended = audioEnded;
const timeline = document.querySelector('.timeline');
function changeTimelinePosition() {
const percentagePosition = (100 * audio.currentTime) / audio.duration;
timeline.style.backgroundSize = `${percentagePosition}% 100%`;
timeline.value = percentagePosition;
}
audio.ontimeupdate = changeTimelinePosition;
function changeSeek() {
const time = (timeline.value * audio.duration) / 100;
audio.currentTime = time;
}
timeline.addEventListener('change', changeSeek);
const soundButton = document.querySelector('.sound-button'),
soundIcon = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
<path fill-rule="evenodd" d="M9.383 3.076A1 1 0 0110 4v12a1 1 0 01-1.707.707L4.586 13H2a1 1 0 01-1-1V8a1 1 0 011-1h2.586l3.707-3.707a1 1 0 011.09-.217zM14.657 2.929a1 1 0 011.414 0A9.972 9.972 0 0119 10a9.972 9.972 0 01-2.929 7.071 1 1 0 01-1.414-1.414A7.971 7.971 0 0017 10c0-2.21-.894-4.208-2.343-5.657a1 1 0 010-1.414zm-2.829 2.828a1 1 0 011.415 0A5.983 5.983 0 0115 10a5.984 5.984 0 01-1.757 4.243 1 1 0 01-1.415-1.415A3.984 3.984 0 0013 10a3.983 3.983 0 00-1.172-2.828 1 1 0 010-1.415z" clip-rule="evenodd" />
</svg>`,
muteIcon = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
<path fill-rule="evenodd" d="M9.383 3.076A1 1 0 0110 4v12a1 1 0 01-1.707.707L4.586 13H2a1 1 0 01-1-1V8a1 1 0 011-1h2.586l3.707-3.707a1 1 0 011.09-.217zM12.293 7.293a1 1 0 011.414 0L15 8.586l1.293-1.293a1 1 0 111.414 1.414L16.414 10l1.293 1.293a1 1 0 01-1.414 1.414L15 11.414l-1.293 1.293a1 1 0 01-1.414-1.414L13.586 10l-1.293-1.293a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>`;
function toggleSound() {
audio.muted = !audio.muted;
soundButton.innerHTML = audio.muted ? muteIcon : soundIcon;
}
soundButton.addEventListener('click', toggleSound);
<div class="audio-player left">
<div class="icon-container">
<img src="coverart1.jpg" style="width: 100%" alt="">
<!--<svg xmlns="http://www.w3.org/2000/svg" class="audio-icon" viewBox="0 0 20 20" fill="currentColor">
<path d="blahblahblahpath" />
</svg>-->
<audio src="audio/1.mp3"></audio>
</div>
<div class="controls">
<button class="player-button">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
<path fill-rule="evenodd" d="blahblahblahpath" />
</svg>
</button>
<input type="range" class="timeline" max="100" value="0">
<button class="sound-button">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
<path fill-rule="evenodd" d="blahblahblahpath" clip-rule="evenodd" />
</svg>
</button>
</div>
</div>
有了这个结构,我不太确定如何为特定玩家index/search(除了知道我应该使用 queryselectALL 并为某些 JS 函数添加 for 循环之外)。
任何修复?目前第一个播放器运行良好,但没有其他播放器响应点击。也许与事件侦听器有关?
beyond knowing that i should probably use queryselectALL and add for loops to some JS functions
这就是重点:您需要为每个播放器实例分配事件侦听器。
let audioPlayers = document.querySelectorAll(".audio-player");
if (audioPlayers.length) {
audioPlayers.forEach(function(audioPlayer, i) {
let audio = audioPlayer.querySelector("audio");
let playerButton = audioPlayer.querySelector(".player-button");
playerButton.addEventListener("click", function(e) {
let current = e.currentTarget;
let audio = current.closest(".audio-player").querySelector("audio");
let btnSvg = current.querySelector(".useBtn");
if (!audio.paused) {
btnSvg.setAttribute("href", "#icon-play");
audio.pause();
} else {
btnSvg.setAttribute("href", "#icon-pause");
audio.play();
}
});
let timeline = audioPlayer.querySelector('.timeline');
timeline.addEventListener('change', function(e) {
let time = (timeline.value * audio.duration) / 100;
audio.currentTime = time;
});
audio.addEventListener('ended', function(e) {
console.log('audio finished');
timeline.value = 0;
});
audio.addEventListener('timeupdate', function(e) {
let percentagePosition = (100 * audio.currentTime) / audio.duration;
timeline.value = percentagePosition;
});
});
}
svg {
display: block;
width: 1em;
}
.player-button {
display: inline-block;
height: 1em;
background: none;
padding: 0;
border: none;
font-size: 1.2em;
position: relative;
bottom: -0.15em;
}
<div class="audio-player left">
<div class="icon-container">
<audio preload="metadata" src="https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3"></audio>
</div>
<div class="controls">
<button class="player-button">
<svg viewBox="0 0 20 20" fill="#3D3132">
<use class="useBtn" href="#icon-play" />
</svg>
</button>
<input type="range" class="timeline" min="0" max="100" step="1" value="0">
</div>
</div>
<div class="audio-player left">
<div class="icon-container">
<audio preload="metadata" src="https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3"></audio>
</div>
<div class="controls">
<button class="player-button">
<svg viewBox="0 0 20 20" fill="#3D3132">
<use class="useBtn" href="#icon-play" />
</svg>
</button>
<input type="range" class="timeline" min="0" max="100" step="1" value="0">
</div>
</div>
<svg class="plyrBtns" style="display:none" aria-hidden="true">
<symbol class="icon icon-play" id="icon-play" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z" clip-rule="evenodd" />
</symbol>
<symbol class="icon icon-pause" id="icon-pause" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd" />
</symbol>
</svg>