zl程序教程

您现在的位置是:首页 >  其它

当前栏目

迷你音乐播放器

音乐 播放器 迷你
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();

链接
添加链接描述