迷你音乐播放器
音乐 播放器 迷你
2023-09-11 14:18:27 时间
HTML
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport"
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no,viewport-fit=cover">
<title>音乐播放器</title>
<!-- 字体图标库 -->
<link rel="stylesheet" href="./font.css">
<link rel="stylesheet" href="./bfq.css">
</head>
<body>
<div class="container">
<div class="bg"></div>
<div class="bg-mask"></div>
<div class="player">
<div class="player-track">
<div class="album-name">牧马城市</div>
<div class="track-name">毛不易 - 牧马城市</div>
<div class="track-time">
<div class="current-time">00:00</div>
<div class="total-time">03:50</div>
</div>
<div class="progress-box">
<div class="hover-time">00:36</div>
<div class="hover-bar"></div>
<div class="progress-bar"></div>
</div>
</div>
<div class="player-content">
<div class="album-cover">
<img src="./牧马城市.jpg" alt="" class="active">
<img src="./水星记.jpg" alt="">
<img src="./麒麟.jpg" alt="">
<img src="./彩虹.jpg" alt="">
<img src="./长安故里.jpg" alt="">
</div>
<div class="play-controls">
<div class="control">
<div class="button play-prev">
<i class="fa fa-step-backward"></i>
</div>
</div>
<div class="control">
<div class="button play-pause">
<i class="fa fa-play"></i>
</div>
</div>
<div class="control">
<div class="button play-next">
<i class="fa fa-step-forward"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="./bfq.js"></script>
</body>
</html>
CSS
* {
/* 初始化 */
margin: 0;
padding: 0;
}
body {
/* 100%窗口高度 */
height: 100vh;
/* 弹性布局 居中显示 */
display: flex;
justify-content: center;
align-items: center;
}
.container {
width: 430px;
height: 100px;
}
/* 模糊背景图 */
.bg {
/* 固定定位 */
position: fixed;
top: -40px;
right: -40px;
bottom: -40px;
left: -40px;
background: url(./牧马城市.jpg) no-repeat;
background-size: cover;
background-position: center;
/* 模糊滤镜 */
filter: blur(40px);
z-index: 1;
}
/* 半透明白色遮罩层 */
.bg-mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(255, 255, 255, 0.5);
z-index: 2;
}
.player {
position: relative;
z-index: 3;
width: 100%;
height: 100%;
}
/* 歌曲信息轨道区域 */
.player-track {
position: absolute;
top: 0;
right: 15px;
bottom: 0;
left: 15px;
padding: 13px 22px 10px 184px;
background-color: rgba(255, 255, 255, 0.8);
border-radius: 15px 15px 0 0;
/* 改变top时的过渡效果 */
transition: top 0.3s ease;
}
/* 歌曲信息轨道区域活动态 */
.player-track.active {
/* 上移 */
top: -95px;
}
.album-name {
color: #333;
font-size: 17px;
font-weight: bold;
}
.track-name {
color: #888;
font-size: 13px;
margin: 3px 0 12px 0;
}
.track-time {
height: 12px;
line-height: 12px;
margin-bottom: 4px;
overflow: hidden;
}
.current-time,
.total-time {
color: #ff668f;
font-size: 11px;
transition: 0.3s ease;
}
.current-time {
float: left;
}
.total-time {
float: right;
}
/* 播放进度区域 */
.progress-box {
position: relative;
height: 4px;
background-color: #ead2d7;
border-radius: 4px;
cursor: pointer;
}
/* 悬停进度条显示时间 */
.hover-time {
position: absolute;
top: -30px;
background-color: rgba(0, 0, 0, 0.8);
color: #fff;
font-size: 12px;
padding: 5px 6px;
border-radius: 4px;
display: none;
}
/* 悬停进度条颜色 */
.hover-bar {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.12);
border-radius: 4px;
z-index: 2;
}
/* 已播放的进度条颜色 */
.progress-bar {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #fd6d94;
border-radius: 4px;
z-index: 1;
width: 0;
/* 改变width时的过渡效果 */
transition: width 0.2s ease;
}
.player-content {
position: relative;
height: 100%;
background-color: #fff;
border-radius: 15px;
z-index: 2;
box-shadow: 0 30px 80px #656565;
}
/* 封面 */
.album-cover {
width: 115px;
height: 115px;
border-radius: 50%;
position: absolute;
top: -40px;
left: 40px;
box-shadow: 0 0 0 10px #fff;
overflow: hidden;
transition: 0.3s ease;
}
/* 唱片中间的小圆点 */
.album-cover::before {
content: "";
width: 20px;
height: 20px;
background-color: #d6dee6;
position: absolute;
top: 50%;
right: 0;
bottom: 0;
left: 0;
border-radius: 50%;
margin: -10px auto auto auto;
box-shadow: inset 0 0 0 2px #fff;
z-index: 1;
}
/* 封面活动态 */
.album-cover.active {
top: -60px;
box-shadow: 0 0 0 4px #fff7f7, 0 30px 50px -15px #afb7c1;
}
.album-cover img {
display: block;
width: 100%;
height: 0%;
object-fit: cover;
opacity: 0;
}
.album-cover img.active {
height: 100%;
opacity: 1;
}
/* 播放时封面旋转 */
.album-cover.active img.active {
/* 执行动画:动画名 时长 线性的 无限次播放 */
animation: rotateAlbumCover 3s linear infinite;
}
/* 控制区 */
.play-controls {
width: 255px;
height: 100%;
float: right;
overflow: hidden;
display: flex;
align-items: center;
padding-right: 2px;
}
.control {
flex: 1;
}
.control .button {
width: 75px;
height: 75px;
display: flex;
justify-content: center;
align-items: center;
background-color: #fff;
border-radius: 6px;
cursor: pointer;
transition: 0.2s ease;
}
.control .button i {
color: #d6dee6;
font-size: 30px;
transition: 0.2s ease;
}
.control .button:hover {
background-color: #d6d6de;
}
.control .button:hover i {
color: #fff;
}
/* 定义动画 */
@keyframes rotateAlbumCover {
0% {
transform: rotateZ(0);
}
100% {
transform: rotateZ(360deg);
}
}
JS
// 要操作的元素
let play_pause = document.querySelector('.play-pause'),
player_track = document.querySelector('.player-track'),
album_cover = document.querySelector('.album-cover'),
bg = document.querySelector('.bg'),
album_name = document.querySelector('.album-name'),
track_name = document.querySelector('.track-name'),
track_time = document.querySelector('.track-time'),
current_time = document.querySelector('.current-time'),
total_time = document.querySelector('.total-time'),
progress_box = document.querySelector('.progress-box'),
hover_time = document.querySelector('.hover-time'),
hover_bar = document.querySelector('.hover-bar'),
progress_bar = document.querySelector('.progress-bar'),
play_prev = document.querySelector('.play-prev'),
play_next = document.querySelector('.play-next');
// 专辑名数组
let albums = ['牧马城市', '水星记', '麒麟', '彩虹', '我叫长安,你叫故里'];
// 歌曲信息数组
let track_names = ['毛不易 - 牧马城市', '郭顶 - 水星记', '早安 - 麒麟', 'TimeZ - 彩虹', '尹昔眠 - 我叫长安,你叫故里'];
// 定义变量
let progress_t, //鼠标在进度条上悬停的位置
progress_loc, //鼠标在进度条上悬停的音频位置
c_m, //悬停音频位置(分钟)
ct_minutes, //悬停播放位置(分)
ct_seconds, //悬停播放位置(秒)
cur_minutes, //当前播放时间(分)
cur_seconds, //当前播放时间(秒)
dur_minutes, //音频总时长(分)
dur_seconds, //音频总时长(秒)
play_progress; //播放进度
// 当前歌曲下标
let cur_index = -1;
// 初始化
function initPlayer() {
audio = new Audio(); //创建音频对象
audio.loop = false; //不循环播放
selectTrack(0);
// 绑定播放暂停按钮的点击事件
play_pause.addEventListener('click', playPause);
// 进度条鼠标移动事件
progress_box.addEventListener('mousemove', function(e) {
showHover(e);
});
// 进度条鼠标离开事件
progress_box.addEventListener('mouseout', hideHover);
// 进度条点击事件
progress_box.addEventListener('click', playFromClickedPos);
// 音频播放位置改变事件
audio.addEventListener('timeupdate', updateCurTime);
// 上一首按钮点击事件
play_prev.addEventListener('click', function() {
selectTrack(-1);
});
// 下一首按钮点击事件
play_next.addEventListener('click', function() {
selectTrack(1);
});
}
// 播放暂停
function playPause() {
setTimeout(function() {
if (audio.paused) {
player_track.classList.add('active');
play_pause.querySelector('.fa').classList = 'fa fa-pause';
album_cover.classList.add('active');
audio.play();
} else {
player_track.classList.remove('active');
play_pause.querySelector('.fa').classList = 'fa fa-play';
album_cover.classList.remove('active');
audio.pause();
}
}, 300);
}
// 显示悬停播放位置弹层
function showHover(e) {
// 计算鼠标在进度条上的悬停位置(当前鼠标的X坐标-进度条在窗口中的left位置)
progress_t = e.clientX - progress_box.getBoundingClientRect().left;
// 计算鼠标在进度条上悬停时的音频位置
// audio.duration 音频总时长
progress_loc = audio.duration * (progress_t / progress_box.getBoundingClientRect().width);
// 设置悬停进度条的宽度(较深部分)
hover_bar.style.width = progress_t + 'px';
// 将悬停音频位置转为分钟
c_m = progress_loc / 60;
ct_minutes = Math.floor(c_m); //分
ct_seconds = Math.floor(progress_loc - ct_minutes * 60); //秒
if (ct_minutes < 10) {
ct_minutes = '0' + ct_minutes;
}
if (ct_seconds < 10) {
ct_seconds = '0' + ct_seconds;
}
if (isNaN(ct_minutes) || isNaN(ct_seconds)) {
hover_time.innerText = '--:--';
} else {
hover_time.innerText = ct_minutes + ':' + ct_seconds;
}
// 设置悬停播放位置弹层的位置并显示
hover_time.style.left = progress_t + 'px';
hover_time.style.marginLeft = '-20px';
hover_time.style.display = 'block';
}
// 隐藏悬停播放位置弹层
function hideHover() {
hover_bar.style.width = '0px';
hover_time.innerText = '00:00';
hover_time.style.left = '0px';
hover_time.style.marginLeft = '0px';
hover_time.style.display = 'none';
}
// 从点击的位置开始播放
function playFromClickedPos() {
// 设置当前播放时间
audio.currentTime = progress_loc;
// 设置进度条宽度
progress_bar.style.width = progress_t + 'px';
// 隐藏悬停播放位置弹层
hideHover();
}
// 改变当前播放时间
function updateCurTime() {
// 当前播放时间(分)
cur_minutes = Math.floor(audio.currentTime / 60);
// 当前播放时间(秒)
cur_seconds = Math.floor(audio.currentTime - cur_minutes * 60);
// 音频总时长(分)
dur_minutes = Math.floor(audio.duration / 60);
// 音频总时长(秒)
dur_seconds = Math.floor(audio.duration - dur_minutes * 60);
// 计算播放进度
play_progress = audio.currentTime / audio.duration * 100;
if (cur_minutes < 10) {
cur_minutes = '0' + cur_minutes;
}
if (cur_seconds < 10) {
cur_seconds = '0' + cur_seconds;
}
if (dur_minutes < 10) {
dur_minutes = '0' + dur_minutes;
}
if (dur_seconds < 10) {
dur_seconds = '0' + dur_seconds;
}
// 设置播放时间
if (isNaN(cur_minutes) || isNaN(cur_seconds)) {
current_time.innerText = '00:00';
} else {
current_time.innerText = cur_minutes + ':' + cur_seconds;
}
// 设置总时长
if (isNaN(dur_minutes) || isNaN(dur_seconds)) {
total_time.innerText = '00:00';
} else {
total_time.innerText = dur_minutes + ':' + dur_seconds;
}
// 设置进度条宽度
progress_bar.style.width = play_progress + '%';
// 播放完毕, 恢复样式
if (play_progress == 100) {
play_pause.querySelector('.fa').classList = 'fa fa-play';
progress_bar.style.width = '0px';
current_time.innerText = '00:00';
player_track.classList.remove('active');
album_cover.classList.remove('active');
}
}
// 切换歌曲(flag: 0=初始, 1=下一首, -1=上一首)
function selectTrack(flag) {
if (flag == 0 || flag == 1) {
++cur_index;
} else {
--cur_index;
}
if (cur_index > -1 && cur_index < albums.length) {
if (flag == 0) {
play_pause.querySelector('.fa').classList = 'fa fa-play';
} else {
play_pause.querySelector('.fa').classList = 'fa fa-pause';
}
progress_bar.style.width = '0px';
current_time.innerText = '00:00';
total_time.innerText = '00:00';
// 当前专辑名
let cur_album = albums[cur_index];
// 当前歌曲信息(歌手 - 歌名)
let cur_track_name = track_names[cur_index];
// 设置音频路径
audio.src = './mp3/' + cur_album + '.mp3';
if (flag != 0) {
// 当切换上一首,下一首时,自动播放
audio.play();
player_track.classList.add('active');
album_cover.classList.add('active');
}
// 设置专辑名
album_name.innerText = cur_album;
// 设置歌曲信息
track_name.innerText = cur_track_name;
// 设置封面
album_cover.querySelector('.active').classList.remove('active');
album_cover.getElementsByTagName('img')[cur_index].classList.add('active');
// 将封面设置为背景大图
bg.style.backgroundImage = 'url(' + album_cover.getElementsByTagName('img')[cur_index].getAttribute('src') + ')';
} else {
// 切换溢出专辑数组时, 恢复cur_index
if (flag == 0 || flag == 1) {
--cur_index;
} else {
++cur_index;
}
}
}
// 初始化播放器
initPlayer();
链接
添加链接描述
相关文章
- 高仿手机QQ音乐之——Android带进度条的开关
- C# (初入江湖)-写个苗苗音乐播放器(什么,播放音乐还要下载软件?那写个吧)
- 利用频谱分析实现音乐无缝隙过度
- 用C语言播放mp3格式的音乐
- 0成本无VPS搭建私人导航、图床、音乐服务器 | vercel freewha
- 微信小程序音乐播放器组件
- vue的keep-alive,后台播放音乐?
- Swift - 制作一个在线流媒体音乐播放器(使用StreamingKit库)
- 音乐播放时跳动的音符
- android获取和展示音乐的频谱
- Swift版音乐播放器(简化版),swift音乐播放器
- 苹果收购已破产流媒体音乐公司 为吸收技术和人才
- SwiftUI 制作个音乐播放器 (教程含源码)AVQueuePlayer
- 毕业设计 安卓音乐播放器APP
- Arduino红外遥控无源蜂鸣器播放音乐
- Unity 工具 之 常用的音乐/音频/语音类插件整理(音乐节拍/可视化/语音聊天/文字转语音等)
- 【历史上的今天】4 月 23 日:YouTube 上传第一个视频;网易云音乐正式上线;数字音频播放器的发明者出生
- 音乐行业如何运用大数据打造下一个“大热门”?