实战教程:如何用JavaScript构建一个功能强大的音乐播放器,兼容本地与在线资源

项目地址:Music Player App

作者:Reza Mehdikhanlou

视频地址:youtube

我将向您展示如何使用 javascript 编写音乐播放器。我们创建一个项目,您可以使用 javascript 从本地文件夹或任何 url 播放音频文件。

项目目录

  • assets
    • 1.jpg
    • 1.mp3
    • 2.jpg
    • 2.mp3
    • 3.jpg
    • 3.mp3
  • index.html
  • index.js
  • style.css

代码

index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <link rel="stylesheet" href="style.css">
    <title>Music Player App</title>
</head>

<body>

    <div class="background">
        <img src="" id="bg-img">
    </div>

    <div class="container">
        <div class="player-img">
            <img src="" class="active" id="cover">
        </div>

        <h2 id="music-title"></h2>
        <h3 id="music-artist"></h3>

        <div class="player-progress" id="player-progress">
            <div class="progress" id="progress"></div>
            <div class="music-duration">
                <span id="current-time">0:00</span>
                <span id="duration">0:00</span>
            </div>
        </div>

        <div class="player-controls">
            <i class="fa-solid fa-backward" title="Previous" id="prev"></i>
            <i class="fa-solid fa-play play-button" title="Play" id="play"></i>
            <i class="fa-solid fa-forward" title="Next" id="next"></i>
        </div>

    </div>

    <script src="index.js"></script>
</body>

</html>

index.js

const image = document.getElementById('cover'),
    title = document.getElementById('music-title'),
    artist = document.getElementById('music-artist'),
    currentTimeEl = document.getElementById('current-time'),
    durationEl = document.getElementById('duration'),
    progress = document.getElementById('progress'),
    playerProgress = document.getElementById('player-progress'),
    prevBtn = document.getElementById('prev'),
    nextBtn = document.getElementById('next'),
    playBtn = document.getElementById('play'),
    background = document.getElementById('bg-img');

const music = new Audio();

const songs = [
    {
        path: 'assets/1.mp3',
        // path:'https://childish.oss-cn-hangzhou.aliyuncs.com/songs/Peel%20Back%20the%20Heart.mp3'
        displayName: 'The Charmer\'s Call',
        cover: 'assets/1.jpg',
        artist: 'Hanu Dixit',
    },
    {
        path: 'assets/2.mp3',
        displayName: 'You Will Never See Me Coming',
        cover: 'assets/2.jpg',
        artist: 'NEFFEX',
    },
    {
        path: 'assets/3.mp3',
        displayName: 'Intellect',
        cover: 'assets/3.jpg',
        artist: 'Yung Logos',
    }
];

let musicIndex = 0;
let isPlaying = false;

function togglePlay() {
    if (isPlaying) {
        pauseMusic();
    } else {
        playMusic();
    }
}

function playMusic() {
    isPlaying = true;
    // Change play button icon
    playBtn.classList.replace('fa-play', 'fa-pause');
    // Set button hover title
    playBtn.setAttribute('title', 'Pause');
    music.play();
}

function pauseMusic() {
    isPlaying = false;
    // Change pause button icon
    playBtn.classList.replace('fa-pause', 'fa-play');
    // Set button hover title
    playBtn.setAttribute('title', 'Play');
    music.pause();
}

function loadMusic(song) {
    music.src = song.path;
    title.textContent = song.displayName;
    artist.textContent = song.artist;
    image.src = song.cover;
    background.src = song.cover;
}

function changeMusic(direction) {
    musicIndex = (musicIndex + direction + songs.length) % songs.length;
    loadMusic(songs[musicIndex]);
    playMusic();
}

function updateProgressBar() {
    const { duration, currentTime } = music;
    const progressPercent = (currentTime / duration) * 100;
    progress.style.width = `${progressPercent}%`;

    const formatTime = (time) => String(Math.floor(time)).padStart(2, '0');
    durationEl.textContent = `${formatTime(duration / 60)}:${formatTime(duration % 60)}`;
    currentTimeEl.textContent = `${formatTime(currentTime / 60)}:${formatTime(currentTime % 60)}`;
}

function setProgressBar(e) {
    const width = playerProgress.clientWidth;
    const clickX = e.offsetX;
    music.currentTime = (clickX / width) * music.duration;
}

playBtn.addEventListener('click', togglePlay);
prevBtn.addEventListener('click', () => changeMusic(-1));
nextBtn.addEventListener('click', () => changeMusic(1));
music.addEventListener('ended', () => changeMusic(1));
music.addEventListener('timeupdate', updateProgressBar);
playerProgress.addEventListener('click', setProgressBar);

loadMusic(songs[musicIndex]);

style.css

@import url('https://fonts.googleapis.com/css2?family=Ubuntu:wght@300;400;500;700&display=swap');

html{
    box-sizing: border-box;
}

body{
    margin: 0;
    font-family: 'Ubuntu', sans-serif;
    font-size: 12px;
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
}

.background{
    position: fixed;
    width: 200%;
    height: 200%;
    top: -50%;
    left: -50%;
    z-index: -1;
}

.background img{
    position: absolute;
    margin: auto;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    min-width: 50%;
    min-height: 50%;
    filter: blur(15px);
    -webkit-filter: blur(50px);
    transform: scale(1.1);
}

.container{
    background-color: #e7e7e7;
    height: 500px;
    width: 400px;
    border-radius: 20px;
    box-shadow: 0 15px 30px rgba(0, 0, 0, 0.3);
    transition: all 0.5s ease;
}

.container:hover{
    box-shadow: 0 15px 30px rgba(0, 0, 0, 0.6);
}

.player-img{
    width: 300px;
    height: 300px;
    position: relative;
    top: -50px;
    left: 50px;
}

.player-img img{
    object-fit: cover;
    border-radius: 20px;
    height: 0;
    width: 0;
    opacity: 0;
    box-shadow: 0 5px 30px 5px rgba(0, 0, 0, 0.5);
}

.player-img:hover img{
    box-shadow: 0 5px 30px 5px rgba(0, 0, 0, 0.8);
}

.player-img img.active{
    width: 100%;
    height: 100%;
    transition: all 0.5s;
    opacity: 1;
}

h2{
    font-size: 25px;
    text-align: center;
    font-weight: 500;
    margin: 10px 0 0;
}

h3{
    font-size: 18px;
    text-align: center;
    font-weight: 500;
    margin: 10px 0 0;
}

.player-progress{
    background-color: #fff;
    border-radius: 5px;
    cursor: pointer;
    margin: 40px 20px 35px;
    height: 6px;
    width: 90%;
}

.progress{
    background-color: #212121;
    border-radius: 5px;
    height: 100%;
    width: 0%;
    transition: width 0.1s linear;
}

.music-duration{
    position: relative;
    top: -25px;
    display: flex;
    justify-content: space-between;
}

.player-controls{
    position: relative;
    top: -15px;
    left: 120px;
    width: 200px;
}

.fa-solid{
    font-size: 30px;
    color: #666;
    margin-right: 30px;
    cursor: pointer;
    user-select: none;
    transition: all 0.3s ease;
}

.fa-solid:hover{
    filter: brightness(40%);
}

.play-button{
    font-size: 44px;
    position: relative;
    top: 3px;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/772852.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

图DFS遍历

DFS遍历图 伪代码 俩函数。 判断图有几个连通分支&#xff1f;就是图的遍历&#xff0c;dfs完了就给他 #include <iostream> #include <cstdlib> #include <bits/stdc.h> #include <vector> using namespace std; const int N102; int n,m,temp1,te…

Python学习笔记28:进阶篇(十七)常见标准库使用之质量控制中的代码质量与风格第二部分

前言 本文是根据python官方教程中标准库模块的介绍&#xff0c;自己查询资料并整理&#xff0c;编写代码示例做出的学习笔记。 根据模块知识&#xff0c;一次讲解单个或者多个模块的内容。 教程链接&#xff1a;https://docs.python.org/zh-cn/3/tutorial/index.html 质量控制…

面试篇-Redis-2+持久化+过期key删除+内存淘汰

文章目录 前言一、你知道Redis 数据是怎么持久化的1.1 Redis 持久化的方式Rdb&#xff1a;1.1.1 主动备份save 命令&#xff1a;1.1.2 Redis 中使用bgsave 进行Rdb 的持久化 &#xff1a; 1.2 Redis 持久化的方式Aof&#xff1a;1.2.1 使用AOF 模式进行数据存储&#xff1a;1.2…

数据库主从复制

目录 一.主从复制架构 二.主从复制原理 三.实现主从复制配置 1.新建主从复制 2.实战遇到问题 3.复制错误解决方法 4.级联 主从复制 5.半同步复制 MySQL数据库的主从复制&#xff08;Master-Slave Replication&#xff09;是一种常见的数据库复制架构&#xff0c;用于提…

越南宣称已成全球第二大手机出口国,富士康翻白眼,为啥限电?

日前越南媒体报道指越南今年前5个月的手机及零部件出口达到224亿美元&#xff0c;同比增长11%&#xff0c;超越印度&#xff0c;成为仅次于中国的全球第二大手机出口国&#xff0c;对此富士康、三星恐怕会有不同的意见。 为越南手机业务做出重要贡献的无疑是富士康、三星等企业…

2.2.1 ROS2案例以及案例分析

1.案例需求 需求1&#xff1a;编写话题通信实现&#xff0c;发布方以某个频率发布一段文本&#xff0c;订阅方订阅消息&#xff0c;并输出在终端。 需求2&#xff1a;编写话题通信实现&#xff0c;发布方以某个频率发布自定义接口消息&#xff0c;订阅方订阅消息&#xff0c;并…

1975react社区问答管理系统开发mysql数据库web结构node.js编程计算机网页源码

一、源码特点 react 社区问答管理系统是一套完善的完整信息管理类型系统&#xff0c;结合react.js框架和node.js后端完成本系统&#xff0c;对理解react node编程开发语言有帮助系统采用node框架&#xff08;前后端分离&#xff09;&#xff09;&#xff0c;系统具有完整的源…

什么是数字体验成熟度,以及数字成熟度的模型计算和实现方法

“开发成功的全渠道数字身份&#xff0c;并通过无缝的数字体验吸引广泛的受众。无论您身在何处&#xff0c;都可以加速数字化转型并促进业务增长。通过直观、全面的工具&#xff0c;并了解您个人的数字体验成熟度水平&#xff0c;超越不断增长的客户期望并超越竞争对手。今天就…

构建LangChain应用程序的示例代码:53、利用多模态大型语言模型在RAG应用中处理混合文档的示例

许多文档包含多种内容类型&#xff0c;包括文本和图像。 然而&#xff0c;在大多数 RAG 应用中&#xff0c;图像中捕获的信息都会丢失。 随着多模态LLMs的出现&#xff0c;比如GPT-4V&#xff0c;如何在RAG中利用图像是值得考虑的。 本篇指南的亮点是&#xff1a; 使用非结…

不到 5 元的随身 WiFi 刷 Debian 系统 做轻量家庭服务器

本文首发于只抄博客,欢迎点击原文链接了解更多内容。 前言 前不久在某宝均价 5 元买了两个随身 WiFi,拆机看了看丝印都是 MSM8916 ,正好是红米 2 同款的骁龙 410 的芯片,可以刷个 Debian 当作家庭服务器来跑一些轻量的服务。 不过手气不是很好,两个都是 512M + 4G 的配置…

【高阶数据结构】B-数、B+树、B*树的原理

文章目录 B树的概念及其特点解析B树的基本操作插入数据插入数据模拟 分析分裂如何维护平衡性分析B树的性能 B树和B*树B树B树的分裂B树的优势 B*B*树的分裂 总结 B树的概念及其特点 B树是一颗多叉的平衡搜索树&#xff0c;广泛应用于数据库和 文件系统中&#xff0c;以保持数据…

Ubuntu20.04突然没网的一种解决办法

本来要学一下点云地图处理&#xff0c;用octomap库&#xff0c;但是提示少了octomap-server库&#xff0c;然后通过下面命令安装的时候&#xff1a; sudo apt install ros-noetic-octomap-server 提示&#xff1a;错误:7 https://mirrors.ustc.edu.cn/ubuntu focal-security …

11 - matlab m_map地学绘图工具基础函数 - 绘制航迹、椭圆、风向玫瑰图和特定的圆形区域的有关函数及其用法

11 - matlab m_map地学绘图工具基础函数 - 绘制航迹、椭圆、风向玫瑰图和特定的圆形区域的有关函数及其用法 0. 引言1. 关于m_track2. 关于m_range_ring3. 关于m_ellipse4. 关于m_windrose5. 结语 0. 引言 本篇介绍下m_map中绘制航迹图函数&#xff08;m_track&#xff09;、绘…

HTTP与HTTPS协议区别及应用场景

HTTP&#xff08;超文本传输​​协议&#xff09;和 HTTPS&#xff08;安全超文本传输​​协议&#xff09;都是用于通过网络传输数据的协议。虽然它们有一些相似之处&#xff0c;但在安全性和数据保护方面也存在显著差异。 在这篇博文中&#xff0c;我们将探讨 HTTP 和 HTTPS…

Hadoop-11-MapReduce JOIN 操作的Java实现 Driver Mapper Reducer具体实现逻辑 模拟SQL进行联表操作

章节内容 上一节我们完成了&#xff1a; MapReduce的介绍Hadoop序列化介绍Mapper编写规范Reducer编写规范Driver编写规范WordCount功能开发WordCount本地测试 背景介绍 这里是三台公网云服务器&#xff0c;每台 2C4G&#xff0c;搭建一个Hadoop的学习环境&#xff0c;供我学…

利用YOLOv8识别自定义模型

一、背景介绍 最近项目需要识别自定义物品&#xff0c;于是学习利用YOLOv8算法&#xff0c;实现物品识别。由于物体类别不再常规模型中&#xff0c;因此需要自己训练相应的模型&#xff0c;特此记录模型训练的过程。 二、训练模型的步骤 1.拍照获取训练图片&#xff08;训练图…

【前端CSS3】CSS显示模式(黑马程序员)

文章目录 一、前言&#x1f680;&#x1f680;&#x1f680;二、CSS元素显示模式&#xff1a;☀️☀️☀️2.1 什么是元素显示模式2.2 块元素2.3 行内元素2.4 行块元素2.5 元素显示模式的转换 三、总结&#x1f680;&#x1f680;&#x1f680; 一、前言&#x1f680;&#x1f…

操作符“->“

title: 操作符"->" date: 2024-01-16 00:00:00 categories: C箭头 tags: 箭头操作以及偏移量计算 #嘎嘎 操作符"->" ->是一个成员访问的操作&#xff0c;它的作用是通过一个指针来访问它所指向的对象的成员变量或成员函数。它的左边必须是一个指…