分享个哪吒面板添加音乐
</style>
<div id="music-player">
<button id="prev" title="上一首">
<svg viewBox="0 0 24 24"><path d="M16 19V5l-11 7z"/></svg>
</button>
<button id="play-pause" title="播放">
<svg id="play-icon" viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg>
<svg id="pause-icon" viewBox="0 0 24 24" style="display:none;">
<rect x="6" y="5" width="4" height="14"/>
<rect x="14" y="5" width="4" height="14"/>
</svg>
</button>
<button id="next" title="下一首">
<svg viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg>
</button>
<span id="song-info">加载中...</span>
</div>
<script>
const songs = [
{
"title": "借口 - 周杰伦",
"src": "https://music.gvrander.eu.org/music/%E5%80%9F%E5%8F%A3-%E5%91%A8%E6%9D%B0%E4%BC%A6.mp3"
},
{
"title": "富士山下 - 陈奕迅",
"src": "https://music.gvrander.eu.org/music/%E5%AF%8C%E5%A3%AB%E5%B1%B1%E4%B8%8B-%E9%99%88%E5%A5%95%E8%BF%85.mp3"
},
{
"title": "小幸运 - 田馥甄",
"src": "https://music.gvrander.eu.org/music/%E5%B0%8F%E5%B9%B8%E8%BF%90-%E7%94%B0%E9%A6%A5%E7%94%84.mp3"
},
{
"title": "年少有为 - 李荣浩",
"src": "https://music.gvrander.eu.org/music/%E5%B9%B4%E5%B0%91%E6%9C%89%E4%B8%BA-%E6%9D%8E%E8%8D%A3%E6%B5%A9.flac"
},
{
"title": "搁浅 - 周杰伦",
"src": "https://music.gvrander.eu.org/music/%E6%90%81%E6%B5%85-%E5%91%A8%E6%9D%B0%E4%BC%A6.flac"
},
{
"title": "晴天 - 周杰伦",
"src": "https://music.gvrander.eu.org/music/%E6%99%B4%E5%A4%A9%20-%20%E5%91%A8%E6%9D%B0%E4%BC%A6.mp3"
},
{
"title": "最长的电影 - 周杰伦",
"src": "https://music.gvrander.eu.org/music/%E6%9C%80%E9%95%BF%E7%9A%84%E7%94%B5%E5%BD%B1-%E5%91%A8%E6%9D%B0%E4%BC%A6.mp3"
},
{
"title": "海阔天空 - Beyond",
"src": "https://music.gvrander.eu.org/music/%E6%B5%B7%E9%98%94%E5%A4%A9%E7%A9%BA-Beyond.mp3"
},
{
"title": "童话 - 光良",
"src": "https://music.gvrander.eu.org/music/%E7%AB%A5%E8%AF%9D-%E5%85%89%E8%89%AF.flac"
},
{
"title": "第一次 - 光良",
"src": "https://music.gvrander.eu.org/music/%E7%AC%AC%E4%B8%80%E6%AC%A1-%E5%85%89%E8%89%AF.mp3"
},
{
"title": "说好不哭 - 周杰伦with阿信",
"src": "https://music.gvrander.eu.org/music/%E8%AF%B4%E5%A5%BD%E4%B8%8D%E5%93%AD-%E5%91%A8%E6%9D%B0%E4%BC%A6with%E9%98%BF%E4%BF%A1.flac"
},
{
"title": "说好的幸福呢 - 周杰伦",
"src": "https://music.gvrander.eu.org/music/%E8%AF%B4%E5%A5%BD%E7%9A%84%E5%B9%B8%E7%A6%8F%E5%91%A2-%E5%91%A8%E6%9D%B0%E4%BC%A6.flac"
}
];
// 每次刷新页面随机一首
let currentSongIndex = Math.floor(Math.random() * songs.length);
let audio = null;
let isPlaying = false;
let hasInteracted = false;
function updateButtonState() {
document.getElementById('play-icon').style.display = isPlaying ? 'none' : 'block';
document.getElementById('pause-icon').style.display = isPlaying ? 'block' : 'none';
document.getElementById('play-pause').title = isPlaying ? '暂停' : '播放';
}
function updateSongInfo() {
document.getElementById('song-info').textContent = songs[currentSongIndex]?.title || '未知音轨';
}
function initAudio() {
if (!audio) {
audio = new Audio();
audio.preload = "auto";
audio.addEventListener('ended', () => {
let nextIndex;
do {
nextIndex = Math.floor(Math.random() * songs.length);
} while (nextIndex === currentSongIndex && songs.length > 1);
currentSongIndex = nextIndex;
loadAndPlay(true);
});
audio.addEventListener('play', () => { isPlaying = true; updateButtonState(); });
audio.addEventListener('pause', () => { isPlaying = false; updateButtonState(); });
}
}
async function loadAndPlay(autoplay = true) {
try {
initAudio();
if (audio.src !== songs[currentSongIndex].src) {
audio.src = songs[currentSongIndex].src;
await new Promise((resolve, reject) => {
audio.addEventListener('loadedmetadata', resolve, { once: true });
audio.addEventListener('error', reject, { once: true });
});
}
updateSongInfo();
if (autoplay) await audio.play();
} catch (err) {
console.log("播放失败:", err);
isPlaying = false;
updateButtonState();
document.getElementById('song-info').textContent = '播放失败,换首试试';
}
}
async function togglePlayPause() {
if (!audio) return;
try {
audio.paused ? await audio.play() : audio.pause();
} catch (err) {
console.log("播放控制失败:", err);
}
}
function playOnFirstInteraction() {
if (hasInteracted) return;
hasInteracted = true;
window.removeEventListener('click', playOnFirstInteraction);
window.removeEventListener('keydown', playOnFirstInteraction);
loadAndPlay(true);
}
window.addEventListener('click', playOnFirstInteraction, { once: true });
window.addEventListener('keydown', playOnFirstInteraction, { once: true });
window.addEventListener('load', () => {
initAudio();
updateSongInfo();
updateButtonState();
});
document.getElementById("play-pause").addEventListener("click", togglePlayPause);
document.getElementById("next").addEventListener("click", async () => {
let nextIndex;
do {
nextIndex = Math.floor(Math.random() * songs.length);
} while (nextIndex === currentSongIndex && songs.length > 1);
currentSongIndex = nextIndex;
await loadAndPlay(true);
});
document.getElementById("prev").addEventListener("click", async () => {
let prevIndex;
do {
prevIndex = Math.floor(Math.random() * songs.length);
} while (prevIndex === currentSongIndex && songs.length > 1);
currentSongIndex = prevIndex;
await loadAndPlay(true);
});
</script>
响应老友要求再修改一版。
位置固定在浏览器左下角,靠左边缘,点击按钮展开播放器。
<style>
#music-container {
position: fixed;
left: 0;
bottom: 20px;
display: flex;
align-items: center;
background: #222;
border-radius: 6px;
overflow: hidden;
box-shadow: 0 0 6px rgba(0,0,0,0.7);
transition: width 0.3s ease;
width: 18px;
height: 50px;
z-index: 9999;
font-family: "微软雅黑", Arial, sans-serif;
font-size: 9px;
}
#music-container.expanded {
width: 190px;
height: 50px;
}
#toggle-btn {
width: 18px;
height: 50px;
background: #333;
border: none;
outline: none;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
padding: 0;
order: 2;
flex-shrink: 0;
z-index: 10;
}
#toggle-btn svg {
fill: #fff;
width: 11px;
height: 11px;
transition: transform 0.3s ease;
}
#toggle-btn.collapsed svg {
transform: rotate(0deg);
}
#toggle-btn.expanded svg {
transform: rotate(180deg);
}
#music-player {
flex: 1 1 auto;
display: none;
flex-direction: row;
align-items: center;
padding: 4px 6px;
color: #eee;
white-space: nowrap;
order: 1;
user-select: none;
overflow: hidden;
}
#music-container.expanded #music-player {
display: flex;
}
#music-player button {
background: #444;
border: none;
color: #eee;
padding: 4px 5px;
margin: 0 2px;
border-radius: 3px;
cursor: pointer;
height: 32px;
flex-shrink: 0;
}
#music-player button svg {
width: 11px;
height: 11px;
fill: #eee;
}
#song-info {
margin-left: 8px;
max-width: 110px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 10px;
}
</style>
<div id="music-container" class="collapsed" aria-label="音乐播放器容器">
<button id="toggle-btn" class="collapsed" title="展开播放器" aria-label="展开音乐播放器">
<svg viewBox="0 0 24 24"><path d="M8 5l8 7-8 7z"/></svg>
</button>
<div id="music-player" aria-label="音乐播放器">
<button id="prev" title="上一首" aria-label="上一首">
<svg viewBox="0 0 24 24"><path d="M16 19V5l-11 7z"/></svg>
</button>
<button id="play-pause" title="播放" aria-label="播放/暂停">
<svg id="play-icon" viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg>
<svg id="pause-icon" viewBox="0 0 24 24" style="display:none;">
<rect x="6" y="5" width="4" height="14"/>
<rect x="14" y="5" width="4" height="14"/>
</svg>
</button>
<button id="next" title="下一首" aria-label="下一首">
<svg viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg>
</button>
<span id="song-info">加载中...</span>
</div>
</div>
<script>
const toggleBtn = document.getElementById('toggle-btn');
const musicContainer = document.getElementById('music-container');
toggleBtn.addEventListener('click', () => {
const isExpanded = musicContainer.classList.toggle('expanded');
if (isExpanded) {
musicContainer.classList.remove('collapsed');
toggleBtn.classList.remove('collapsed');
toggleBtn.classList.add('expanded');
toggleBtn.title = "收起播放器";
toggleBtn.setAttribute('aria-label', '收起音乐播放器');
} else {
musicContainer.classList.remove('expanded');
musicContainer.classList.add('collapsed');
toggleBtn.classList.remove('expanded');
toggleBtn.classList.add('collapsed');
toggleBtn.title = "展开播放器";
toggleBtn.setAttribute('aria-label', '展开音乐播放器');
}
});
// 播放列表示例,这里只放了1首,替换为你的列表即可
const songs = [
{
"title": "说好的幸福呢 - 周杰伦",
"src": "https://music.gvrander.eu.org/music/%E8%AF%B4%E5%A5%BD%E7%9A%84%E5%B9%B8%E7%A6%8F%E5%91%A2-%E5%91%A8%E6%9D%B0%E4%BC%A6.flac"
}
];
let currentSongIndex = Math.floor(Math.random() * songs.length);
let audio = null;
let isPlaying = false;
let hasInteracted = false;
function updateButtonState() {
document.getElementById('play-icon').style.display = isPlaying ? 'none' : 'block';
document.getElementById('pause-icon').style.display = isPlaying ? 'block' : 'none';
document.getElementById('play-pause').title = isPlaying ? '暂停' : '播放';
}
function updateSongInfo() {
document.getElementById('song-info').textContent = songs[currentSongIndex]?.title || '未知音轨';
}
function initAudio() {
if (!audio) {
audio = new Audio();
audio.preload = "auto";
audio.addEventListener('ended', () => {
let nextIndex;
do {
nextIndex = Math.floor(Math.random() * songs.length);
} while (nextIndex === currentSongIndex && songs.length > 1);
currentSongIndex = nextIndex;
loadAndPlay(true);
});
audio.addEventListener('play', () => { isPlaying = true; updateButtonState(); });
audio.addEventListener('pause', () => { isPlaying = false; updateButtonState(); });
}
}
async function loadAndPlay(autoplay = true) {
try {
initAudio();
if (audio.src !== songs[currentSongIndex].src) {
audio.src = songs[currentSongIndex].src;
await new Promise((resolve, reject) => {
audio.addEventListener('loadedmetadata', resolve, { once: true });
audio.addEventListener('error', reject, { once: true });
});
}
updateSongInfo();
if (autoplay) await audio.play();
} catch (err) {
console.log("播放失败:", err);
isPlaying = false;
updateButtonState();
document.getElementById('song-info').textContent = '播放失败,换首试试';
}
}
async function togglePlayPause() {
if (!audio) return;
try {
audio.paused ? await audio.play() : audio.pause();
} catch (err) {
console.log("播放控制失败:", err);
}
}
function playOnFirstInteraction() {
if (hasInteracted) return;
hasInteracted = true;
window.removeEventListener('click', playOnFirstInteraction);
window.removeEventListener('keydown', playOnFirstInteraction);
loadAndPlay(true);
}
window.addEventListener('click', playOnFirstInteraction, { once: true });
window.addEventListener('keydown', playOnFirstInteraction, { once: true });
window.addEventListener('load', () => {
initAudio();
updateSongInfo();
updateButtonState();
});
document.getElementById("play-pause").addEventListener("click", togglePlayPause);
document.getElementById("next").addEventListener("click", async () => {
let nextIndex;
do {
nextIndex = Math.floor(Math.random() * songs.length);
} while (nextIndex === currentSongIndex && songs.length > 1);
currentSongIndex = nextIndex;
await loadAndPlay(true);
});
document.getElementById("prev").addEventListener("click", async () => {
let prevIndex;
do {
prevIndex = Math.floor(Math.random() * songs.length);
} while (prevIndex === currentSongIndex && songs.length > 1);
currentSongIndex = prevIndex;
await loadAndPlay(true);
});
</script>