原生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 统计时间
Mar 09 Javascript
jquery特效 幻灯片效果示例代码
Jul 16 Javascript
javaScript年份下拉列表框内容为当前年份及前后50年
May 28 Javascript
Javascript实现图片轮播效果(二)图片序列节点的控制实现
Feb 17 Javascript
angular.js分页代码的实例
Jul 27 Javascript
js中获取jsp表单中radio类型的值简单实例
Aug 15 Javascript
Angular ng-repeat指令实例以及扩展部分
Dec 26 Javascript
jQuery图片拖动组件Dropzone用法示例
Jan 17 Javascript
jQuery表格(Table)基本操作实例分析
Mar 10 Javascript
layer设置maxWidth及maxHeight解决方案
Jul 26 Javascript
微信小程序实现同时上传多张图片
Feb 03 Javascript
JavaScript常用工具函数汇总(浏览器环境)
Sep 17 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
简单的页面缓冲技术
2006/10/09 PHP
解析php根据ip查询所在地区(非常有用,赶集网就用到)
2013/07/01 PHP
调试WordPress中定时任务的相关PHP脚本示例
2015/12/10 PHP
PHP自定义函数实现格式化秒的方法
2016/09/14 PHP
PHP使用SWOOLE扩展实现定时同步 MySQL 数据
2017/04/09 PHP
Yii框架常见缓存应用实例小结
2019/09/09 PHP
jQuery 瀑布流 绝对定位布局(二)(延迟AJAX加载图片)
2012/05/23 Javascript
JS中showModalDialog 的使用解析
2013/04/17 Javascript
JavaScript实现的一个计算数字步数的算法分享
2014/12/06 Javascript
基于javascript代码实现通过点击图片显示原图片
2015/11/29 Javascript
JavaScript通过HTML的class来获取HTML元素的方法总结
2016/05/24 Javascript
为Jquery EasyUI 组件加上清除功能的方法(详解)
2017/04/13 jQuery
ES6新特性五:Set与Map的数据结构实例分析
2017/04/21 Javascript
vue element-ui table表格滚动加载方法
2018/03/02 Javascript
JavaScript创建对象的常用方式总结
2018/08/10 Javascript
解决Layui选择全部,换页checkbox复选框重新勾选的问题方法
2018/08/14 Javascript
Vue中的nextTick作用和几个简单的使用场景
2021/01/25 Vue.js
python中os操作文件及文件路径实例汇总
2015/01/15 Python
Python2.x和3.x下maketrans与translate函数使用上的不同
2015/04/13 Python
python集合用法实例分析
2015/05/30 Python
Python装饰器用法示例小结
2018/02/11 Python
Python如何调用JS文件中的函数
2019/08/16 Python
pytorch 修改预训练model实例
2020/01/18 Python
python通过安装itchat包实现微信自动回复收到的春节祝福
2020/01/19 Python
Bluebella美国官网:英国性感内衣品牌
2018/10/04 全球购物
7 For All Mankind官网:美国加州洛杉矶的高级牛仔服装品牌
2018/12/20 全球购物
如果有两个类A,B,怎么样才能使A在发生一个事件的时候通知B
2016/03/12 面试题
四川成都导游欢迎词
2014/01/18 职场文书
市场营销管理毕业生自荐信
2014/03/03 职场文书
促销活动总结怎么写
2014/06/25 职场文书
幼儿园秋季开学寄语
2014/08/02 职场文书
个人租房协议书样本
2014/10/01 职场文书
2015年领导班子工作总结
2015/05/23 职场文书
婚宴祝酒词大全
2015/08/10 职场文书
Win11安全功能升级:内置防网络钓鱼功能
2022/04/08 数码科技
Python内置类型集合set和frozenset的使用详解
2022/04/26 Python