💜 网页音乐播放器隐藏在右侧
功能说明:
- 初始状态:播放器隐藏在右侧,只显示圆形专辑封面
- 点击封面:在隐藏状态下可播放/暂停音乐
- 点击封面:展开完整播放器界面
- 完整功能:播放控制、进度条、播放列表等
- 关闭按钮:点击右上角X可收起播放器
隐藏效果:

展开的效果:

代码如下
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>圆形封面音乐播放器</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
text-align: center;
color: white;
}
h1 {
margin-bottom: 30px;
text-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
}
.description {
background: rgba(255, 255, 255, 0.1);
padding: 20px;
border-radius: 10px;
margin-bottom: 30px;
backdrop-filter: blur(10px);
}
/* 迷你播放器样式 */
.mini-player {
position: fixed;
right: 0;
top: 50%;
transform: translateY(-50%);
width: 70px;
height: 70px;
background: rgba(0, 0, 0, 0.8);
box-shadow: -2px 0 10px rgba(0, 0, 0, 0.3);
z-index: 1000;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50% 0 0 50%;
}
.mini-player:hover {
background: rgba(0, 0, 0, 0.9);
}
.album-cover-mini {
width: 60px;
height: 60px;
border-radius: 50%;
overflow: hidden;
border: 2px solid rgba(255, 255, 255, 0.2);
}
.album-cover-mini img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
/* 完整播放器样式 */
.full-player {
position: fixed;
right: -330px;
top: 50%;
transform: translateY(-50%);
width: 330px;
-height: 500px;
background: rgba(0, 0, 0, 0.9);
box-shadow: -5px 0 15px rgba(0, 0, 0, 0.3);
transition: all 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55);
z-index: 1001;
display: flex;
flex-direction: column;
border-radius: 10px 0 0 10px;
}
.full-player.expanded {
right: 0;
}
.player-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 20px;
background: rgba(255, 71, 87, 0.9);
border-radius: 10px 0 0 0;
}
.player-title {
font-size: 18px;
font-weight: bold;
color: white;
}
.close-btn {
background: none;
border: none;
color: white;
font-size: 20px;
cursor: pointer;
width: 30px;
height: 30px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.3s;
}
.close-btn:hover {
background: rgba(255, 255, 255, 0.2);
}
.player-content {
flex: 1;
padding: 20px;
overflow-y: auto;
}
.current-track {
text-align: center;
margin-bottom: 30px;
}
.current-album-cover {
width: 200px;
height: 200px;
border-radius: 50%;
overflow: hidden;
margin: 0 auto 20px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
border: 3px solid rgba(255, 255, 255, 0.3);
}
.current-album-cover img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
.track-info h2 {
font-size: 20px;
margin-bottom: 5px;
}
.track-info p {
color: #aaa;
font-size: 14px;
}
.controls-section {
margin: 30px 0;
}
.progress-container {
margin-bottom: 20px;
}
.progress-info {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
font-size: 12px;
color: #aaa;
}
.progress-bar {
width: 100%;
height: 4px;
background: rgba(255, 255, 255, 0.1);
border-radius: 2px;
overflow: hidden;
cursor: pointer;
}
.progress {
height: 100%;
background: #ff4757;
width: 0%;
transition: width 0.1s;
}
.player-controls {
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
margin: 20px 0;
}
.control-btn {
background: rgba(255, 255, 255, 0.1);
border: none;
width: 40px;
height: 40px;
border-radius: 50%;
color: white;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
}
.control-btn:hover {
background: rgba(255, 255, 255, 0.2);
transform: scale(1.1);
}
.control-btn.play-pause {
width: 50px;
height: 50px;
background: #ff4757;
}
.playlist-section {
margin-top: 20px;
}
.playlist-title {
font-size: 16px;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.playlist-items {
max-height: 150px;
overflow-y: auto;
}
.playlist-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 15px;
background: rgba(255, 255, 255, 0.05);
border-radius: 5px;
margin-bottom: 8px;
cursor: pointer;
transition: background 0.2s;
}
.playlist-item:hover {
background: rgba(255, 255, 255, 0.1);
}
.playlist-item.active {
background: rgba(255, 71, 87, 0.2);
border-left: 3px solid #ff4757;
}
.song-info {
flex: 1;
}
.song-title {
font-size: 14px;
margin-bottom: 3px;
}
.song-artist {
font-size: 12px;
color: #aaa;
}
.song-duration {
font-size: 12px;
color: #aaa;
}
/* 滚动条样式 */
.playlist-items::-webkit-scrollbar {
width: 5px;
}
.playlist-items::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
}
.playlist-items::-webkit-scrollbar-thumb {
background: #ff4757;
border-radius: 5px;
}
/* 旋转动画 */
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.playing-img {
animation: rotate 10s linear infinite;
}
.paused-img {
animation-play-state: paused;
}
</style>
</head>
<body>
<div class="container">
<h1>圆形封面音乐播放器</h1>
<div class="description">
<h2>功能说明:</h2>
<p>1. 初始状态:播放器隐藏在右侧,只显示圆形专辑封面</p>
<p>2. 点击封面:在隐藏状态下可播放/暂停音乐</p>
<p>3. 点击封面:展开完整播放器界面</p>
<p>4. 完整功能:播放控制、进度条、播放列表等</p>
<p>5. 关闭按钮:点击右上角X可收起播放器</p>
</div>
</div>
<!-- 迷你播放器(右侧隐藏状态) -->
<div class="mini-player" id="miniPlayer">
<div class="album-cover-mini">
<img src="https://picsum.photos/200/200?music" alt="专辑封面" id="miniAlbumCover">
</div>
</div>
<!-- 完整播放器 -->
<div class="full-player" id="fullPlayer">
<div class="player-header">
<div class="player-title">音乐播放器</div>
<button class="close-btn" id="closePlayer">×</button>
</div>
<div class="player-content">
<div class="current-track">
<div class="current-album-cover">
<img src="https://picsum.photos/200/200?music" alt="专辑封面" id="currentAlbumCover">
</div>
<div class="track-info">
<h2 id="currentSongTitle">歌曲名称</h2>
<p id="currentSongArtist">艺术家</p>
</div>
</div>
<div class="controls-section">
<div class="progress-container">
<div class="progress-info">
<span id="currentTime">00:00</span>
<span id="totalTime">00:00</span>
</div>
<div class="progress-bar" id="progressBar">
<div class="progress" id="progress"></div>
</div>
</div>
<div class="player-controls">
<button class="control-btn prev-btn" id="prevBtn">◀◀</button>
<button class="control-btn play-pause" id="playPauseBtn">▶</button>
<button class="control-btn next-btn" id="nextBtn">▶▶</button>
</div>
</div>
<div class="playlist-section">
<div class="playlist-title">播放列表</div>
<div class="playlist-items" id="playlistItems">
<!-- 播放列表动态生成 -->
</div>
</div>
</div>
<audio id="audioElement"></audio>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// 播放列表数据
const playlist = [
{
id: 1,
title: '青舞',
artist: '来自网络',
src: 'https://audio.jukehost.co.uk/SN3m8tzBVwZE8HuHWEkPlulULCpXNddg.mp3',
cover: 'https://picsum.photos/200/200?music1',
duration: '00:55'
},
{
id: 2,
title: '易燃易爆炸',
artist: '陈粒',
src: 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3',
cover: 'https://picsum.photos/200/200?music2',
duration: '04:20'
},
{
id: 3,
title: '知否知否',
artist: '胡夏/郁可唯',
src: 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-3.mp3',
cover: 'https://picsum.photos/200/200?music3',
duration: '04:55'
},
{
id: 4,
title: '起风了',
artist: '买辣椒也用券',
src: 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-4.mp3',
cover: 'https://picsum.photos/200/200?music4',
duration: '05:30'
}
];
// 元素引用
const audio = document.getElementById('audioElement');
const miniPlayer = document.getElementById('miniPlayer');
const fullPlayer = document.getElementById('fullPlayer');
const closeBtn = document.getElementById('closePlayer');
const playPauseBtn = document.getElementById('playPauseBtn');
const prevBtn = document.getElementById('prevBtn');
const nextBtn = document.getElementById('nextBtn');
const progressBar = document.getElementById('progressBar');
const progress = document.getElementById('progress');
const currentTimeEl = document.getElementById('currentTime');
const totalTimeEl = document.getElementById('totalTime');
const currentAlbumCover = document.getElementById('currentAlbumCover');
const miniAlbumCover = document.getElementById('miniAlbumCover');
const currentSongTitle = document.getElementById('currentSongTitle');
const currentSongArtist = document.getElementById('currentSongArtist');
const playlistItems = document.getElementById('playlistItems');
let currentSongIndex = 0;
let isPlaying = false;
let isDragging = false;
// 初始化播放器
function init() {
loadSong(currentSongIndex);
renderPlaylist();
setupEventListeners();
}
// 加载歌曲
function loadSong(index) {
const song = playlist[index];
audio.src = song.src;
currentSongTitle.textContent = song.title;
currentSongArtist.textContent = song.artist;
currentAlbumCover.src = song.cover;
miniAlbumCover.src = song.cover;
totalTimeEl.textContent = song.duration;
// 重置旋转状态
if (isPlaying) {
playSong();
} else {
pauseSong();
}
updateActivePlaylistItem(index);
}
// 渲染播放列表
function renderPlaylist() {
playlistItems.innerHTML = '';
playlist.forEach((song, index) => {
const item = document.createElement('div');
item.className = 'playlist-item';
item.innerHTML = `
<div class="song-info">
<div class="song-title">${song.title}</div>
<div class="song-artist">${song.artist}</div>
</div>
<div class="song-duration">${song.duration}</div>
`;
item.addEventListener('click', () => {
currentSongIndex = index;
loadSong(index);
if (isPlaying) {
playSong();
}
});
playlistItems.appendChild(item);
});
updateActivePlaylistItem(currentSongIndex);
}
// 更新活动播放列表项
function updateActivePlaylistItem(index) {
const items = document.querySelectorAll('.playlist-item');
items.forEach((item, i) => {
item.classList.toggle('active', i === index);
});
}
// 播放歌曲
function playSong() {
isPlaying = true;
audio.play();
playPauseBtn.textContent = '❚❚';
// 确保移除所有可能干扰的类
currentAlbumCover.classList.remove('paused-img');
miniAlbumCover.classList.remove('paused-img');
// 添加旋转类
currentAlbumCover.classList.add('playing-img');
miniAlbumCover.classList.add('playing-img');
}
// 暂停歌曲
function pauseSong() {
isPlaying = false;
audio.pause();
playPauseBtn.textContent = '▶';
// 确保移除所有可能干扰的类
currentAlbumCover.classList.remove('playing-img');
miniAlbumCover.classList.remove('playing-img');
// 添加暂停类
currentAlbumCover.classList.add('paused-img');
miniAlbumCover.classList.add('paused-img');
}
// 更新进度
function updateProgress() {
if (isDragging) return;
const currentTime = audio.currentTime;
const duration = audio.duration;
if (duration) {
const progressPercent = (currentTime / duration) * 100;
progress.style.width = `${progressPercent}%`;
// 更新时间显示
const currentMinutes = Math.floor(currentTime / 60);
const currentSeconds = Math.floor(currentTime % 60);
currentTimeEl.textContent = `${currentMinutes}:${currentSeconds.toString().padStart(2, '0')}`;
}
}
// 设置事件监听器
function setupEventListeners() {
// 展开播放器
miniPlayer.addEventListener('click', function(e) {
e.stopPropagation();
fullPlayer.classList.add('expanded');
});
// 收起播放器
closeBtn.addEventListener('click', function(e) {
e.stopPropagation();
fullPlayer.classList.remove('expanded');
});
// 迷你播放器点击播放
miniPlayer.addEventListener('click', function(e) {
if (!fullPlayer.classList.contains('expanded')) {
togglePlayPause();
e.stopPropagation();
}
});
// 播放/暂停按钮
playPauseBtn.addEventListener('click', togglePlayPause);
// 上一首/下一首
prevBtn.addEventListener('click', () => {
currentSongIndex = (currentSongIndex - 1 + playlist.length) % playlist.length;
loadSong(currentSongIndex);
if (isPlaying) playSong();
});
nextBtn.addEventListener('click', () => {
currentSongIndex = (currentSongIndex + 1) % playlist.length;
loadSong(currentSongIndex);
if (isPlaying) playSong();
});
// 进度条控制
progressBar.addEventListener('click', (e) => {
const rect = progressBar.getBoundingClientRect();
const percent = (e.clientX - rect.left) / rect.width;
audio.currentTime = percent * audio.duration;
});
progressBar.addEventListener('mousedown', () => isDragging = true);
document.addEventListener('mouseup', () => isDragging = false);
progressBar.addEventListener('mousemove', (e) => {
if (isDragging) {
const rect = progressBar.getBoundingClientRect();
const percent = (e.clientX - rect.left) / rect.width;
audio.currentTime = percent * audio.duration;
}
});
// 音频事件
audio.addEventListener('timeupdate', updateProgress);
audio.addEventListener('ended', () => {
currentSongIndex = (currentSongIndex + 1) % playlist.length;
loadSong(currentSongIndex);
if (isPlaying) playSong();
});
// 点击外部收起播放器
document.addEventListener('click', (e) => {
if (!fullPlayer.contains(e.target) && !miniPlayer.contains(e.target)) {
fullPlayer.classList.remove('expanded');
}
});
}
// 切换播放/暂停
function togglePlayPause() {
if (isPlaying) {
pauseSong();
} else {
playSong();
}
}
// 初始化
init();
});
</script>
</body>
</html>
演示效果
阅读:50
发布时间: