原生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 相关文章推荐
JS操作数据库的实例代码
Oct 17 Javascript
javascript 获取HTML DOM父、子、临近节点
Jun 16 Javascript
jQuery制作可自定义大小的拼图游戏
Mar 30 Javascript
JavaScript监听文本框回车事件并过滤文本框空格的方法
Apr 16 Javascript
Bootstrap插件全集
Jul 18 Javascript
前端程序员必须知道的高性能Javascript知识
Aug 24 Javascript
详解AngularJs ui-router 路由的简单介绍
Apr 26 Javascript
微信小程序签到功能
Oct 31 Javascript
详解微信小程序开发之formId使用(模板消息)
Aug 27 Javascript
在vue中利用v-html按分号将文本换行的例子
Nov 14 Javascript
简单了解three.js 着色器材质
Aug 03 Javascript
Vue使用axios引起的后台session不同操作
Aug 14 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计算程序运行时间的简单例子分享
2014/05/10 PHP
Json_encode防止汉字转义成unicode的方法
2016/02/25 PHP
PHP获取客户端及服务器端IP的封装类
2016/07/21 PHP
PHP实现负载均衡session共享redis缓存操作示例
2018/08/22 PHP
javascript操作数组详解
2014/12/17 Javascript
使用Node.js实现HTTP 206内容分片的教程
2015/06/23 Javascript
JavaScript简单修改窗口大小的方法
2015/08/03 Javascript
JS组件Bootstrap ContextMenu右键菜单使用方法
2016/04/17 Javascript
让你彻底掌握es6 Promise的八段代码
2017/07/26 Javascript
react-native android状态栏的实现
2018/06/15 Javascript
element-ui表格列金额显示两位小数的方法
2018/08/24 Javascript
基于vue和react的spa进行按需加载的实现方法
2018/09/29 Javascript
layui表格数据重载
2019/07/27 Javascript
vue进入页面时不在顶部,检测滚动返回顶部按钮问题及解决方法
2019/10/30 Javascript
vue项目实现图片上传功能
2019/12/23 Javascript
关于javascript中的promise的用法和注意事项(推荐)
2021/01/15 Javascript
[01:32]TI奖金增速竟因它再创新高!DOTA2勇士令状不朽珍藏Ⅰ饰品欣赏
2018/05/18 DOTA
Python contextlib模块使用示例
2015/02/18 Python
Python实现命令行通讯录实例教程
2016/08/18 Python
浅谈Python中函数的定义及其调用方法
2019/07/19 Python
Python学习笔记之列表和成员运算符及列表相关方法详解
2019/08/22 Python
tensorflow指定GPU与动态分配GPU memory设置
2020/02/03 Python
Python实现列表中非负数保留,负数转化为指定的数值方式
2020/06/04 Python
使用Numpy对特征中的异常值进行替换及条件替换方式
2020/06/08 Python
python中format函数如何使用
2020/06/22 Python
意大利团购网站:Groupon意大利
2016/10/11 全球购物
英国排名第一的停车场运营商:NCP
2019/08/26 全球购物
New delete 与malloc free 的联系与区别
2013/02/04 面试题
学生自我评价范文
2014/02/02 职场文书
霸王洗发水广告词
2014/03/14 职场文书
心得体会的写法
2014/09/05 职场文书
商场圣诞节活动总结
2015/05/06 职场文书
员工工作心得体会
2019/05/07 职场文书
分享15个Webpack实用的插件!!!
2021/03/31 Javascript
基于Python的EasyGUI学习实践
2021/05/07 Python
《游戏王:大师决斗》将推出新卡牌包4月4日上线
2022/03/31 其他游戏