原生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 相关文章推荐
How to Auto Include a Javascript File
Feb 02 Javascript
js将字符串转成正则表达式的实现方法
Nov 13 Javascript
JQuery处理json与ajax返回JSON实例代码
Jan 03 Javascript
jquery统计用户选中的复选框的个数
Jun 06 Javascript
node.js中的fs.chown方法使用说明
Dec 16 Javascript
深入理解JavaScript系列(44):设计模式之桥接模式详解
Mar 04 Javascript
jQuery的load()方法及其回调函数用法实例
Mar 25 Javascript
jQuery实现简洁的导航菜单效果
Nov 23 Javascript
Mac下使用charles遇到的问题以及解决办法
Jan 10 Javascript
详解vue2.0的Element UI的表格table列时间戳格式化
Jun 13 Javascript
10分钟彻底搞懂Http的强制缓存和协商缓存(小结)
Aug 30 Javascript
jQuery实现的网站banner图片无缝轮播效果完整实例
Jan 28 jQuery
详解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生成xml简单实例代码
2009/12/16 PHP
PHP命名空间(namespace)原理与用法详解
2019/12/11 PHP
tp5.1 框架数据库-数据集操作实例分析
2020/05/26 PHP
javascript下function声明一些小结
2007/12/28 Javascript
javascript 建设银行登陆键盘
2008/06/10 Javascript
Jquery中对数组的操作代码
2011/08/12 Javascript
JavaScript fontcolor方法入门实例(按照指定的颜色来显示字符串)
2014/10/17 Javascript
深入理解JQuery中的事件与动画
2016/05/18 Javascript
Node.js数据库操作之查询MySQL数据库(二)
2017/03/04 Javascript
js实现一个猜数字游戏
2017/03/31 Javascript
详解ElementUI之表单验证、数据绑定、路由跳转
2017/06/21 Javascript
Angular实现的简单查询天气预报功能示例
2017/12/27 Javascript
js中如何完美的解析数据
2018/03/18 Javascript
剖析Angular Component的源码示例
2018/03/23 Javascript
详解vue-cli脚手架中webpack配置方法
2018/08/22 Javascript
vue移动端微信授权登录插件封装的实例
2018/08/28 Javascript
对angularJs中ng-style动态改变样式的实例讲解
2018/09/30 Javascript
jQuery AJAX与jQuery事件的分析讲解
2019/02/18 jQuery
Element Breadcrumb 面包屑的使用方法
2020/07/26 Javascript
python中pycurl库的用法实例
2014/09/30 Python
编写Python脚本使得web页面上的代码高亮显示
2015/04/24 Python
python使用opencv对图像mask处理的方法
2019/07/05 Python
Python Flask上下文管理机制实例解析
2020/03/16 Python
Python Unittest原理及基本使用方法
2020/11/06 Python
日本面向世界,国际级的免税在线购物商城:DOKODEMO
2017/02/01 全球购物
德国最新街头服饰网上商店:BODYCHECK
2019/09/15 全球购物
巴塞罗那观光通票:Barcelona Pass
2019/10/30 全球购物
CSS实现fullpage.js全屏滚动效果的示例代码
2021/03/24 HTML / CSS
儿子婚宴答谢词
2014/01/09 职场文书
土木建筑学生自我评价
2014/01/14 职场文书
房屋买卖协议书
2014/04/10 职场文书
个人委托书怎么写
2014/09/17 职场文书
大学生自荐材料范文
2014/12/30 职场文书
2015年会计个人工作总结
2015/04/02 职场文书
雷锋的故事观后感
2015/06/10 职场文书
大学运动会通讯稿
2015/07/18 职场文书