Skip to content

Latest commit

 

History

History
470 lines (408 loc) · 17.8 KB

CN.md

File metadata and controls

470 lines (408 loc) · 17.8 KB

logo

react-jinke-music-player

🎵 也许是颜值最高,最好用的一个响应式 React HTML5 音频播放器组件 : )

npm npm npm version Coverage Status

English Doc

安装

使用 yarn:

yarn add react-jinke-music-player

或者 npm

npm install react-jinke-music-player --save

预览

迷你模式

mini mode

白天主题

light theme

黑夜主题

dark theme

移动端

mobile

例子

在线访问 : https://lijinke666.github.io/react-music-player/

实际应用 : 李金珂的小屋

本地访问 : http://localhost:8081/

例子示例代码

使用

import React from 'react'
import ReactDOM from 'react-dom'
import ReactJkMusicPlayer from 'react-jinke-music-player'
import 'react-jinke-music-player/assets/index.css'

ReactDOM.render(
  <ReactJkMusicPlayer {...options} />,
  document.getElementById('root'),
)

API

中文版本文档可能不完整, 请以英文版为准, 维护两个版本太累了

| 属性 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | --- | --- | --- | | className | string | - | 附加的 className | | audioLists | object[] | - | 播放列表 : {name: "YOUR_AUDIO_NAME",singer: "YOUR_AUDIO_SINGER_NAME",cover: "YOUR_AUDIO_COVER",musicSrc: "YOUR_AUDIO_SRC"} | | theme | string | dark | 播放器主题 可选 'light'(白天) 和 'dark'(黑夜) 两种 | | defaultPosition | object | {top:0,left:0} | 当播放器是迷你模式时的初始位 比如 {top:0,left:0} or {top:'20%',left:"20%"} | | playModeText | object | {order: "order",orderLoop: "orderLoop",singleLoop: "singleLoop",shufflePlay:"shufflePlay"}| 播放模式对应的文字 | | playModeShowTime |number|600| 切换播放模式时提示语的显示时间,单位毫秒 | | bounds |object,string|body| 拖拽边界 可以是一个具体的字符串,比如body,也可以是具体的值 left,top,right,bottom| | preload |boolean,string|false| 是否在页面加载后立即加载音频。可选值auto | metadata | none true | false如果preload=true默认会 设置 preload="auto" | | remember |boolean|false| 是否记住当前播放状态,比如音量,播放状态,下次访问时继续播放 | | glassBg |boolean|false| 是否显示毛玻璃背景效果 | | remove |boolean|true| 音乐是否可以被删除 | | defaultPlayIndex |number|0| 默认从第几首歌开始播放, 当值 超过 或低于 可播放数 默认为最大播放数 和 最小播放数 | | openText |string | ReactNode|open| 迷你模式时播放器的打开文案 | | closeText |string | ReactNode|close| 迷你模式时播放器的关闭文案 | | panelTitle |string | ReactNode|PlayList| 播放列表显示的标题 | | emptyText |string | ReactNode|no music| 播放列表为空时显示的文字 | | checkedText |string | ReactNode|-| 播放器主题开关 选中的文字 | | unCheckedText |string | ReactNode|-| 播放器主题开关 未选中的文字 | | defaultPlayMode |string|order| 默认的播放模式 可选order,orderLoop,singleLoop,shufflePlay| | mode |string|mini| 播放器的默认模式 可选mini,full| | once |boolean|false| 在默认情况下 'audioPlay' 函数 会在你 每次暂停后再次播放 触发 , 如果 你只想 让 'audioPlay' 在 音乐初始化播放的时候触发一次,你可以设置 为true| | autoPlay |boolean|true| 是否在加载完成后随即播放音频 | | toggleMode |boolean|true| 是否可以 从迷你模式 切换到 完整模式 , 或者 完整模式 切换到 迷你模式 | | drag |boolean|true| 当播放器是迷你模式时 是否可以对其进行拖拽 | | seeked |boolean|true| 是否能拖动或点击进度条 调整播放进度 | | showMiniModeCover |boolean|true| 在迷你模式时, 是否显示 封面图 | | showMiniProcessBar |boolean|false| 在迷你模式时, 是否显示 圆形进度条 | | showProgressLoadBar |boolean|true| 显示音频加载进度条 | | showPlay |boolean|true| 是否显示播放按钮 | | showReload |boolean|true| 是否显示重放按钮 | | showDownload |boolean|true| 是否显示下载按钮 | | showPlayMode |boolean|true| 是否显示切换播放模式按钮 | | showThemeSwitch |boolean|true| 是否显示主题切换开关 | | extendsContent |array | ReactNode | string | boolean|-| 如果默认的功能按钮不满足你 你可以自定义扩展 比如<>按钮1 按钮2</>| | controllerTitle |string | ReactNode|| 播放器模拟模式封面显示的文字 | | defaultVolume |number|1| 播放器初始音量, 范围0-1| | loadAudioErrorPlayNext |number|true| 当前音频加载加载失败时是否尝试播放下一首 | | onAudioDownload |function(audioInfo)|-| 音频下载 的 钩子函数 | | onAudioPlay |function(audioInfo)|-| 音频播放 的 钩子函数 | | onAudioPause |function(audioInfo)|-| 音频暂停 的 钩子函数 | | onAudioSeeked |function(audioInfo)|-| 进度条被点击或者拖动改变播放进度的 钩子函数 | | onAudioVolumeChange |function(volume)|-| 音量改变的 钩子函数 范围0.0-1.0| | onAudioEnded |function(currentPlayId,audioLists,audioInfo)|-| 当前音频播放结束的 钩子函数 | | onAudioAbort |function(currentPlayId,audioLists,audioInfo)|-| 当前音频播放中断的 钩子函数 | | onAudioProgress |function(audioInfo)|-| 音频正在播放中的 钩子函数 | | onAudioError |function(errMsg,currentPlayId,audioLists,audioInfo)|-| 音频播放失败的 钩子函数 | | onAudioReload |function(audioInfo)|-| 音频重新播放的 钩子函数 | | onAudioListsChange |function(currentPlayId,audioLists,audioInfo)|-| 播放列表发生改变时的 钩子函数 | | onAudioPlayTrackChange |function(currentPlayId,audioLists,audioInfo)|-| 当前播放的音乐发生改变时的 钩子函数 | | onAudioPlayModeChange |function(playMode)|-| 播放模式发生改变时的 钩子函数 | | onAudioListsPanelChange |function(panelVisible)|-| 播放列表打开或关闭的 钩子函数 | | onThemeChange |function(theme)|-| 主题切换后的 钩子函数 | | onModeChange |function(mode)|-| 模式切换发生改变时的 钩子函数 | | onAudioListsSortEnd |function(fromIndex,toIndex)|-| 列表歌曲拖拽后 钩子函数 | | onAudioLyricChange |function(lineNum, currentLyric)|-| 当前播放的歌词改变回调 | | getContainer |() => HTMLElement\|Selectors|document.body| 播放器挂载的节点 默认在 body | | getAudioInstance |(instance: HTMLAudioElement) => void|-| 获取原始的 audio 实例, 可以用它所有的 api 做你想做的事情 | | autoHiddenCover |boolean|false| 当前歌曲没有封面图时是否不渲染对应的 dom 节点 | | onBeforeAudioDownload |(audioInfo: ReactJkMusicPlayerAudioInfo) => Promise|-| 转换下载歌曲的文件名,路径等 | | clearPriorAudioLists |boolean|false| 更新歌曲列表时, 是否清除之前的列表 | | autoPlayInitLoadPlayList |boolean|false| 歌曲列表更新后, 是否自动播放 | | spaceBar |boolean|false| 是否可以通过空格键控制音乐的播放与暂停 | | showDestroy |boolean|false| 是否显示销毁按钮 | | onBeforeDestroy |function(currentPlayId,audioLists,audioInfo)|-| 销毁之前处理函数 | | onDestroyed |function(currentPlayId,audioLists,audioInfo)|-| 销毁之后的回调 | | customDownloader |function(downloadInfo: TransformedDownloadAudioInfo)|-| 自定义下载器 | | audioTitle |string | (audioInfo: ReactJkMusicPlayerAudioInfo) => string|{name} - {signer}` | 自定义音乐显示名称, 默认歌曲名-歌手 |

自定义操作按钮

如果播放器自带的功能不能满足你的需求, 可以自己实现操作按钮 UI, 会同步播放器对应的状态, 并触发钩子函数, 支持功能:

  • 播放
  • 暂停
  • 重新播放
  • 改变当前播放位置
  • 改变播放倍速
  • 改变音量
  • 销毁播放器
class App extends React.Component {
  constructor() {
    this.audioInstance = null
  }
  render() {
    return (
      <>
        <ReactJkMusicPlayer
          getAudioInstance={(instance) => (this.audioInstance = instance)}
        />
        <button onClick={() => this.audioInstance.play()}>播放</button>
        <button onClick={() => this.audioInstance.pause()}>暂停</button>
        <button onClick={() => this.audioInstance.load()}>重新播放</button>
        <button onClick={() => (this.audioInstance.currentTime = 40)}>
          改变当前播放位置
        </button>
        <button onClick={() => (this.audioInstance.playbackRate = 2)}>
          改变播放倍速
        </button>
        <button onClick={() => (this.audioInstance.volume = 0.2)}>
          改变音量
        </button>
        <button onClick={() => this.audioInstance.destroy()}>销毁播放器</button>
      </>
    )
  }
}

毛玻璃效果

<ReactJkMusicPlayer glassBg />

glass-1

glass-2

自定义下载器

eg. https://www.npmjs.com/package/file-saver

const customDownloader = (downloadInfo) => {
  const link = document.createElement('a')
  link.href = downloadInfo.src // a.mp3
  link.download = downloadInfo.filename || 'test'
  document.body.appendChild(link)
  link.click()
}
;<ReactJkMusicPlayer
  audioLists={[{ src: 'a.mp3' }]}
  customDownloader={customDownloader}
/>

// 配合 onBeforeAudioDownload 使用
const onBeforeAudioDownload = () => {
  return Promise.resolve({
    src: '1.mp3',
  })
}

const customDownloader = (downloadInfo) => {
  console.log(downloadInfo.src) // 1.mp3
}
;<ReactJkMusicPlayer customDownloader={customDownloader} />

关闭/销毁 播放器

const onBeforeDestroy = (currentPlayId, audioLists, audioInfo) => {
  return new Promise((resolve, reject) => {
    // 返回一个 Promise, 这里可以做一些自定义的校验
    if (window.confirm('是否关闭?')) {
      // 调用 resolve, 播放器正常关闭/销毁
      resolve()
    } else {
      // 调用 reject, 本次操作无效.
      reject()
    }
  })
}

const onDestroyed = (currentPlayId, audioLists, audioInfo) => {
  console.log('onDestroyed:', currentPlayId, audioLists, audioInfo)
}

ReactDOM.render(
  <ReactJkMusicPlayer
    showDestroy
    onBeforeDestroy={onBeforeDestroy}
    onDestroyed={onDestroyed}
  />,
)

开发

git clone https://github.com/lijinke666/react-music-player.git
yarn | npm install
yarn start | npm start
访问 `http://localhost:8081/`

单元测试

npm run test

音乐列表 数据结构

Like This

interface ReactJkMusicPlayerAudioList {
  name: string | React.ReactNode,
  singer?: string | React.ReactNode,
  cover: string,
  musicSrc: string | () => Promise<string>,
  lyric?: string
  [key: string]: any
}>

返回的音乐信息

Like This

interface ReactJkMusicPlayerAudioInfo {
  cover: string
  currentTime: number
  duration: number
  ended: boolean
  musicSrc: string
  muted: boolean
  name: string
  networkState: number
  paused: boolean
  played: any
  readyState: number
  startDate: any
  volume: number
  lyric: string
  [key: string]: any
}

参数

export interface ReactJkMusicPlayerProps {
  audioLists: Array<ReactJkMusicPlayerAudioList>
  theme?: ReactJkMusicPlayerTheme
  mode?: ReactJkMusicPlayerMode
  defaultPlayMode?: ReactJkMusicPlayerPlayMode
  drag?: boolean
  seeked?: boolean
  autoPlay?: boolean
  playModeText?: {
    order: string | React.ReactNode
    orderLoop: string | React.ReactNode
    singleLoop: string | React.ReactNode
    shufflePlay: string | React.ReactNode
  }
  panelTitle?: string | React.ReactNode
  closeText?: string | React.ReactNode
  openText?: string | React.ReactNode
  emptyText?: string | React.ReactNode
  controllerTitle?: string | React.ReactNode
  defaultPosition?: {
    top: number | string
    left: number | string
    right: number | string
    bottom: number | string
  }
  onAudioPlay?: (audioInfo: ReactJkMusicPlayerAudioInfo) => void
  onAudioPause?: (audioInfo: ReactJkMusicPlayerAudioInfo) => void
  onAudioEnded?: (
    currentPlayId: string,
    audioLists: Array<ReactJkMusicPlayerAudioList>,
    audioInfo: ReactJkMusicPlayerAudioInfo,
  ) => void
  onAudioAbort?: (
    currentPlayId: string,
    audioLists: Array<ReactJkMusicPlayerAudioList>,
    audioInfo: ReactJkMusicPlayerAudioInfo,
  ) => void
  onAudioVolumeChange?: (volume: number) => void
  onAudioError?: (
    errMsg: any,
    currentPlayId: string,
    audioLists: Array<ReactJkMusicPlayerAudioList>,
    audioInfo: ReactJkMusicPlayerAudioInfo,
  ) => void
  onAudioProgress?: (audioInfo: ReactJkMusicPlayerAudioInfo) => void
  onAudioSeeked?: (audioInfo: ReactJkMusicPlayerAudioInfo) => void
  onAudioDownload?: (
    audioInfo: ReactJkMusicPlayerAudioInfo,
    transformedDownloadAudioInfo: TransformedDownloadAudioInfo,
  ) => void
  onAudioReload?: (audioInfo: ReactJkMusicPlayerAudioInfo) => void
  onThemeChange?: (theme: ReactJkMusicPlayerTheme) => void
  onAudioListsChange?: (
    currentPlayId: string,
    audioLists: Array<ReactJkMusicPlayerAudioList>,
    audioInfo: ReactJkMusicPlayerAudioInfo,
  ) => void
  onPlayModeChange?: (playMode: ReactJkMusicPlayerPlayMode) => void
  onModeChange?: (mode: ReactJkMusicPlayerMode) => void
  onAudioListsPanelChange?: (panelVisible: boolean) => void
  onAudioPlayTrackChange?: (fromIndex: number, endIndex: number) => void
  onAudioListsSortEnd?: (
    currentPlayId: string,
    audioLists: Array<ReactJkMusicPlayerAudioList>,
    audioInfo: ReactJkMusicPlayerAudioInfo,
  ) => void
  showDownload?: boolean
  showPlay?: boolean
  showReload?: boolean
  showPlayMode?: boolean
  showThemeSwitch?: boolean
  showMiniModeCover?: boolean
  showDestroy?: boolean
  toggleMode?: boolean
  once?: boolean
  extendsContent?:
    | Array<React.ReactNode | string>
    | React.ReactNode
    | boolean
    | string
  checkedText?: string | React.ReactNode
  unCheckedText?: string | React.ReactNode
  defaultVolume?: number
  playModeShowTime?: number
  bounds?: string | React.ReactNode
  showMiniProcessBar?: boolean
  loadAudioErrorPlayNext?: boolean
  preload?: boolean | 'auto' | 'metadata' | 'none'
  glassBg?: boolean
  remember?: boolean
  remove?: boolean
  defaultPlayIndex?: number
  playIndex?: number
  lyricClassName?: string
  emptyLyricText?: string | React.ReactNode
  showLyric?: boolean
  getContainer?: () => HTMLElement
  getAudioInstance?: (instance: HTMLAudioElement) => void
  autoHiddenCover?: boolean
  onBeforeAudioDownload?: (
    audioInfo: ReactJkMusicPlayerAudioInfo,
  ) => Promise<TransformedDownloadAudioInfo>
  clearPriorAudioLists?: boolean
  autoPlayInitLoadPlayList?: boolean
  spaceBar?: boolean
  onBeforeDestroy?: (
    currentPlayId: string,
    audioLists: Array<ReactJkMusicPlayerAudioList>,
    audioInfo: ReactJkMusicPlayerAudioInfo,
  ) => Promise<void>
  onDestroyed?: (
    currentPlayId: string,
    audioLists: Array<ReactJkMusicPlayerAudioList>,
    audioInfo: ReactJkMusicPlayerAudioInfo,
  ) => Promise<void>
  customDownloader?: (downloadAudioInfo: TransformedDownloadAudioInfo) => void
  audioTitle?: ((audioInfo: ReactJkMusicPlayerAudioInfo) => string) | string
}

export interface TransformedDownloadAudioInfo {
  src: string
  filename?: string
  mimeType?: string
}

export interface ReactJkMusicPlayerInstance extends HTMLAudioElement {
  destroy: () => void
}

许可证

MIT