原生JS实现音乐播放器的示例代码


Posted in Javascript onFebruary 25, 2021

本文主要介绍了原生JS实现音乐播放器的示例代码,分享给大家,具体如下:

效果图

原生JS实现音乐播放器的示例代码

音乐播放器

  • 播放控制
  • 播放进度条控制
  • 歌词显示及高亮
  • 播放模式设置

播放器属性归类

按照播放器的功能划分,对播放器的属性和DOM元素归类,实现同一功能的元素和属性保存在同一对象中,便于管理和操作

const control = { //存放播放器控制
  play: document.querySelector('#myplay'),
 ...
  index: 2,//当前播放歌曲序号
 ...
}

const audioFile = { //存放歌曲文件及相关信息
  file: document.getElementsByTagName('audio')[0],
  currentTime: 0,
  duration: 0,
}

const lyric = { // 歌词显示栏配置
  ele: null,
  totalLyricRows: 0,
  currentRows: 0,
  rowsHeight: 0,
}

const modeControl = { //播放模式
  mode: ['顺序', '随机', '单曲'],
  index: 0
}

const songInfo = { // 存放歌曲信息的DOM容器
  name: document.querySelector('.song-name'),
 ...
}

播放控制

功能:控制音乐的播放和暂停,上一首,下一首,播放完成及相应图标修改
audio所用API:audio.play() 和 audio.pause()和audio ended事件

// 音乐的播放和暂停,上一首,下一首控制
control.play.addEventListener('click',()=>{
  control.isPlay = !control.isPlay;
  playerHandle();
} );
control.prev.addEventListener('click', prevHandle);
control.next.addEventListener('click', nextHandle);
audioFile.file.addEventListener('ended', nextHandle);

function playerHandle() {
  const play = control.play;
  control.isPlay ? audioFile.file.play() : audioFile.file.pause();
  if (control.isPlay) {
 //音乐播放,更改图标及开启播放动画
    play.classList.remove('songStop');
    play.classList.add('songStart');
    control.albumCover.classList.add('albumRotate');
    control.albumCover.style.animationPlayState = 'running';
  } else {
    //音乐暂停,更改图标及暂停播放动画
 ...
  }
}


function prevHandle() {  // 根据播放模式重新加载歌曲
  const modeIndex = modeControl.index;
  const songListLens = songList.length;
  if (modeIndex == 0) {//顺序播放
    let index = --control.index;
    index == -1 ? (index = songListLens - 1) : index;
    control.index = index % songListLens;
  } else if (modeIndex == 1) {//随机播放
    const randomNum = Math.random() * (songListLens - 1);
    control.index = Math.round(randomNum);
  } else if (modeIndex == 2) {//单曲
  }
  reload(songList);
}

function nextHandle() {
  const modeIndex = modeControl.index;
  const songListLens = songList.length;
  if (modeIndex == 0) {//顺序播放
    control.index = ++control.index % songListLens;
  } else if (modeIndex == 1) {//随机播放
    const randomNum = Math.random() * (songListLens - 1);
    control.index = Math.round(randomNum);
  } else if (modeIndex == 2) {//单曲
  }
  reload(songList);
}

播放进度条控制

功能:实时更新播放进度,点击进度条调整歌曲播放进度
audio所用API:audio timeupdate事件,audio.currentTime

// 播放进度实时更新
audioFile.file.addEventListener('timeupdate', lyricAndProgressMove);
// 通过拖拽调整进度
control.progressDot.addEventListener('click', adjustProgressByDrag);
// 通过点击调整进度
control.progressWrap.addEventListener('click', adjustProgressByClick);

播放进度实时更新:通过修改相应DOM元素的位置或者宽度进行修改

function lyricAndProgressMove() {
  const audio = audioFile.file;
  const controlIndex = control.index;
 // 歌曲信息初始化
  const songLyricItem = document.getElementsByClassName('song-lyric-item');
  if (songLyricItem.length == 0) return;
  let currentTime = audioFile.currentTime = Math.round(audio.currentTime);
  let duration = audioFile.duration = Math.round(audio.duration);

  //进度条移动
  const progressWrapWidth = control.progressWrap.offsetWidth;
  const currentBarPOS = currentTime / duration * 100;
  control.progressBar.style.width = `${currentBarPOS.toFixed(2)}%`;
  const currentDotPOS = Math.round(currentTime / duration * progressWrapWidth);
  control.progressDot.style.left = `${currentDotPOS}px`;

  songInfo.currentTimeSpan.innerText = formatTime(currentTime);

}

拖拽调整进度:通过拖拽移动进度条,并且同步更新歌曲播放进度

function adjustProgressByDrag() {
  const fragBox = control.progressDot;
  const progressWrap = control.progressWrap
  drag(fragBox, progressWrap)
}

function drag(fragBox, wrap) {
  const wrapWidth = wrap.offsetWidth;
  const wrapLeft = getOffsetLeft(wrap);

  function dragMove(e) {
    let disX = e.pageX - wrapLeft;
    changeProgressBarPos(disX, wrapWidth)
  }
  fragBox.addEventListener('mousedown', () => { //拖拽操作
    //点击放大方便操作
    fragBox.style.width = `14px`;fragBox.style.height = `14px`;fragBox.style.top = `-7px`;
    document.addEventListener('mousemove', dragMove);
    document.addEventListener('mouseup', () => {
      document.removeEventListener('mousemove', dragMove);
      fragBox.style.width = `10px`;fragBox.style.height = `10px`;fragBox.style.top = `-4px`;
    })
  });
}

function changeProgressBarPos(disX, wrapWidth) { //进度条状态更新
  const audio = audioFile.file
  const duration = audioFile.duration
  let dotPos
  let barPos

  if (disX < 0) {
    dotPos = -4
    barPos = 0
    audio.currentTime = 0
  } else if (disX > 0 && disX < wrapWidth) {
    dotPos = disX
    barPos = 100 * (disX / wrapWidth)
    audio.currentTime = duration * (disX / wrapWidth)
  } else {
    dotPos = wrapWidth - 4
    barPos = 100
    audio.currentTime = duration
  }
  control.progressDot.style.left = `${dotPos}px`
  control.progressBar.style.width = `${barPos}%`
}

点击进度条调整:通过点击进度条,并且同步更新歌曲播放进度

function adjustProgressByClick(e) {

  const wrap = control.progressWrap;
  const wrapWidth = wrap.offsetWidth;
  const wrapLeft = getOffsetLeft(wrap);
  const disX = e.pageX - wrapLeft;
  changeProgressBarPos(disX, wrapWidth)
}

歌词显示及高亮

功能:根据播放进度,实时更新歌词显示,并高亮当前歌词(通过添加样式)
audio所用API:audio timeupdate事件,audio.currentTime

// 歌词显示实时更新
audioFile.file.addEventListener('timeupdate', lyricAndProgressMove);

function lyricAndProgressMove() {
  const audio = audioFile.file;
  const controlIndex = control.index;

  const songLyricItem = document.getElementsByClassName('song-lyric-item');
  if (songLyricItem.length == 0) return;
  let currentTime = audioFile.currentTime = Math.round(audio.currentTime);
  let duration = audioFile.duration = Math.round(audio.duration);
  let totalLyricRows = lyric.totalLyricRows = songLyricItem.length;
  let LyricEle = lyric.ele = songLyricItem[0];
  let rowsHeight = lyric.rowsHeight = LyricEle && LyricEle.offsetHeight;
  //歌词移动
  lrcs[controlIndex].lyric.forEach((item, index) => {
    if (currentTime === item.time) {
      lyric.currentRows = index;
      songLyricItem[index].classList.add('song-lyric-item-active');
      index > 0 && songLyricItem[index - 1].classList.remove('song-lyric-item-active');
      if (index > 5 && index < totalLyricRows - 5) {
        songInfo.lyricWrap.scrollTo(0, `${rowsHeight * (index - 5)}`)
      }

    }
  })
}

播放模式设置

功能:点击跳转播放模式,并修改相应图标
audio所用API:无

// 播放模式设置
control.mode.addEventListener('click', changePlayMode);

function changePlayMode() {
  modeControl.index = ++modeControl.index % 3;
  const mode = control.mode;
  modeControl.index === 0 ?
    mode.setAttribute("class", "playerIcon songCycleOrder") :
    modeControl.index === 1 ?
      mode.setAttribute("class", "playerIcon songCycleRandom ") :
      mode.setAttribute("class", "playerIcon songCycleOnly")
}

项目预览

代码地址:https://github.com/hcm083214/audio-player

到此这篇关于原生JS实现音乐播放器的示例代码的文章就介绍到这了,更多相关JS 音乐播放器内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
基于Jquery的文字自动截取(提供源代码)
Aug 09 Javascript
JS实现模拟百度搜索“2012世界末日”网页地震撕裂效果代码
Oct 31 Javascript
使用jQuery或者原生js实现鼠标滚动加载页面新数据
Mar 06 Javascript
node.js 和HTML5开发本地桌面应用程序
Dec 13 Javascript
ES6学习笔记之Set和Map数据结构详解
Apr 07 Javascript
AngularJS中使用three.js的实例详解
Jul 21 Javascript
webpack 样式加载的实现原理
Jun 12 Javascript
解决bootstrap模态框数据缓存的问题方法
Aug 10 Javascript
bootstrap实现点击删除按钮弹出确认框的实例代码
Aug 16 Javascript
微信小程序开发之点击按钮退出小程序的实现方法
Apr 26 Javascript
JS运算符简单用法示例
Jan 19 Javascript
VUE 实现element upload上传图片到阿里云
Aug 12 Javascript
详解vite2.0配置学习(typescript版本)
Feb 25 #Javascript
详解vite+ts快速搭建vue3项目以及介绍相关特性
Feb 25 #Vue.js
利用 Chrome Dev Tools 进行页面性能分析的步骤说明(前端性能优化)
Feb 24 #Javascript
Nest.js散列与加密实例详解
Feb 24 #Javascript
JS canvas实现画板和签字板功能
Feb 23 #Javascript
基于vue-simple-uploader封装文件分片上传、秒传及断点续传的全局上传插件功能
Feb 23 #Vue.js
js实现验证码干扰(动态)
Feb 23 #Javascript
You might like
在php和MySql中计算时间差的方法
2011/04/22 PHP
php的chr和ord函数实现字符加减乘除运算实现代码
2011/12/05 PHP
什么情况下可以不写PHP的闭合标签“?&gt;”
2014/08/28 PHP
Zend Framework入门教程之Zend_View组件用法示例
2016/12/09 PHP
JavaScript 原型继承
2011/12/26 Javascript
Array.prototype.concat不是通用方法反驳[译]
2012/09/20 Javascript
使用js完成节点的增删改复制等的操作
2014/01/02 Javascript
js Object2String方便查看js对象内容
2014/11/24 Javascript
简单谈谈jQuery(function(){})与(function(){})(jQuery)
2014/12/19 Javascript
Javascript闭包用法实例分析
2015/01/23 Javascript
JS实现至少包含字母、大小写数字、字符的密码等级的两种方法
2015/02/03 Javascript
js实现仿QQ秀换装效果的方法
2015/03/04 Javascript
深入分析node.js的异步API和其局限性
2016/09/05 Javascript
微信小程序 toast 详解及实例代码
2016/11/09 Javascript
Javascrip实现文字跳动特效
2016/11/27 Javascript
jQuery实现动态添加、删除按钮及input输入框的方法
2017/04/27 jQuery
Angular如何引入第三方库的方法详解
2017/07/13 Javascript
js实现继承的方法及优缺点总结
2019/05/08 Javascript
layui导出所有数据的例子
2019/09/10 Javascript
微信小程序错误this.setData报错及解决过程
2019/09/18 Javascript
详解C++编程中一元运算符的重载
2016/01/19 Python
python3+PyQt5实现自定义窗口部件Counters
2018/04/20 Python
Django集成搜索引擎Elasticserach的方法示例
2019/06/04 Python
python 字符串常用方法汇总详解
2019/09/16 Python
Python利用FFT进行简单滤波的实现
2020/02/26 Python
Jupyter安装拓展nbextensions及解决官网下载慢的问题
2021/03/03 Python
CSS3制作彩色进度条样式的代码示例分享
2016/06/23 HTML / CSS
canvas实现圆形进度条动画的示例代码
2017/12/26 HTML / CSS
美国最大的存储市场:SpareFoot
2018/07/23 全球购物
美国按摩椅批发网站:Titan Chair
2018/12/27 全球购物
编写用C语言实现的求n阶阶乘问题的递归算法
2014/10/21 面试题
客服端调用EJB对象的几个基本步骤
2012/01/15 面试题
表扬信格式
2014/01/12 职场文书
我爱幼儿园演讲稿
2014/09/11 职场文书
限期整改通知书
2015/04/22 职场文书
2016开学第一课心得体会
2016/01/23 职场文书