10.0.4 • Published 2 years ago

muon-next-music-player v10.0.4

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

본 프로젝트는 이 프로젝트 의 포크입니다. 주식회사 뮤즐리에서 MuOn프로젝트 개발을 위해 사용합니다.

:package: 설치 방법

yarn을 사용하는 경우 :

yarn add muon-next-music-player

npm을 사용하는 경우 :

npm install muon-next-music-player --save

:framed_picture: 스크린샷

미니모드

mini mode

밝은 테마

light theme

어두운 테마

dark theme

모바일 버전

mobile

:sparkles: 진행 목록

:memo: 사용방법

import React from 'react'
import ReactDOM from 'react-dom'
import ReactMuOnMusicPlayer from 'muon-next-music-player'
import 'muon-next-music-player/assets/index.css'

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

:clipboard: API

NameTypeDefaultDescription
classNamestring-Additional CSS class for the root DOM node
audioListsAudioListProps[]-Detail
themelight | dark | autodarkcolor of the music player theme dark, light, auto (follow system)light
localezh_CN | en_US | CustomLocaleen_USDetaillight
iconCustomize player icon-Customize player iconlight
defaultPositionobject{top:0,left:0}audio controller initial position with left,top,right,and bottom
playModeShowTimenumber600play mode toggle show time (ms)
boundsobject,numberbodyspecifies movement boundaries. Accepted values: parent restricts movement within the node's offsetParent (nearest node with position relative or absolute), or a selector, restricts movement within the targeted node An object with left, top, right, and bottom properties. These indicate how far in each direction the draggable can be moved.
preloadboolean,stringfalseWhether to load audio immediately after the page loads. can be set to auto | metadata | none true | falseifpreload=true preload="auto"
rememberbooleanfalseThe next time you access the player, do you keep the last state
glassBgbooleanfalseWhether the player's background displays frosted glass effect
removebooleantrueThe Audio Can be deleted
defaultPlayIndexnumber0Default play index of the audio player
playIndexnumber0play index of the audio player
defaultPlayModestringorderdefault play mode of the audio player options can be set to order,orderLoop,singleLoop,shufflePlay or omitted
modestringminiaudio theme switch checkedText can be set to mini,full or omitted
oncebooleanfalseThe default audioPlay handle function will be played again after each pause, If you only want to trigger it once, you can set 'true'
autoPlaybooleantrueWhether the audio is played after loading is completed. mobile devices are invalid autoplay-policy-changes
toggleModebooleantrueWhether you can switch between two modes, full => mini or mini => full
dragbooleantrueaudio controller is can be drag of the "mini" mode
seekedbooleantrueWhether you can drag or click the progress bar to play in the new progress.
showMiniModeCoverbooleantrueaudio cover is show of the "mini" mode
showMiniProcessBarbooleanfalseaudio progress circle bar is show of the "mini" mode
showProgressLoadBarbooleantrueDisplays the audio load progress bar.
showPlaybooleantrueplay button display of the audio player panel
showReloadbooleantruereload button display of the audio player panel
showDownloadbooleantruedownload button display of the audio player panel
showPlayModebooleantrueplay mode toggle button display of the audio player panel
showThemeSwitchbooleantruetheme toggle switch display of the audio player panel
showLyricbooleanfalseaudio lyric button display of the audio player panel
showMediaSessionbooleanfalsehttps://web.dev/media-session/
lyricClassNamestring-audio lyric class name
extendsContentReactNode \| boolean \| string-Extensible custom content like <><button>button1</button> <button>button2</button></>
defaultVolumenumber1default volume of the audio player , range 0-1
loadAudioErrorPlayNextbooleantrueWhether to try playing the next audio when the current audio playback fails
responsivebooleantrueWhether to turn on the response mode, if set false, audio controller always show desktop ui
onAudioDownloadfunction(audioInfo)-audio is downloaded handle
onAudioPlayfunction(audioInfo)-audio play handle
onAudioPausefunction(audioInfo)-audio pause handle
onAudioSeekedfunction(audioInfo)-When the user has moved/jumped to a new location in audio handle
onAudioVolumeChangefunction(volume)-When the volume has changed handle min = 0.0 max = 1.0
onAudioEndedfunction(currentPlayId,audioLists,audioInfo)-The single song is ended handle
onAudioAbortfunction(currentPlayId, audioLists, audioInfo)-audio load abort The target event like {...,audioName:xx,audioSrc:xx,playMode:xx}
onAudioProgressfunction(audioInfo)-audio play progress handle
onAudioErrorfunction(errMsg,currentPlayId, audioLists, audioInfo)-audio load failed error handle
onAudioReloadfunction(audioInfo)-audio reload handle
onAudioListsChangefunction(currentPlayId,audioLists,audioInfo)-audio lists change handle
onAudioPlayTrackChangefunction(currentPlayId,audioLists,audioInfo)-audio current play track change handle
onAudioPlayModeChangefunction(playMode)-play mode change handle
onAudioListsPanelChangefunction(panelVisible)-audio lists panel change handle
onThemeChangefunction(theme)-theme change handle
onModeChangefunction(mode)-mode change handle
onAudioListsSortEndfunction(oldIndex,newIndex)-audio lists sort end handle, use SortableJS
onAudioLyricChangefunction(lineNum, currentLyric)-audio lyric change handle
getContainer() => HTMLElement | Selectorsdocument.bodyReturn the mount node for Music player
getAudioInstance(instance: HTMLAudioElement) => void-get origin audio element instance , you can use it do everything
autoHiddenCoverbooleanfalseAuto hide the cover photo if no cover photo is available
onBeforeAudioDownload(audioInfo: ReactMuOnMusicPlayerAudioInfo) => Promise<TransformedDownloadAudioInfo>-transform download audio info before
clearPriorAudioListsbooleanfalseReplace a new playlist with the first loaded playlist and reset playIndex to 0
autoPlayInitLoadPlayListbooleanfalsePlay your new play list right after your new play list is loaded turn false.
spaceBarbooleanfalsePlay and pause audio through space bar (Desktop effective).
showDestroybooleanfalseDestroy player button display
onBeforeDestroyfunction(currentPlayId,audioLists,audioInfo)-custom destroy handler before
onDestroyedfunction(currentPlayId,audioLists,audioInfo)-player destroyed handle
customDownloaderfunction(downloadInfo: TransformedDownloadAudioInfo)-custom download handle
onCoverClickfunction(mode,audioLists,audioInfo)-audio cover clicked handle
onPlayIndexChangefunction(playIndex)-audio play index change handle
quietUpdatebooleanfalseDetail
renderAudioTitle(audioInfo, isMobile) => ReactNode-use locale.audioTitle to set audio tag title, the api can render custom jsx element for display
mobileMediaQuerystring(max-width: 768px) and (orientation : portrait)custom mobile media query string, eg use the mobile version UI on iPad. https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries
volumeFade{ fadeIn: number(ms), fadeOut: number(ms) }-audio fade in and out. Detail
sortableOptionsobject{swap: true, animation: 100, swapClass: 'audio-lists-panel-sortable-highlight-bg'}SortableJs Options
restartCurrentOnPrevbooleanfalseRestarts the current track when trying to play previous song, if the current time of the song is more than 1 second

:bulb: 오퍼레이션 UI 커스터마이징

Support feature:

  • play
  • pause
  • reload
  • change play time
  • change playback rate
  • change volume
  • destroy audio player
  • toggle play
  • clear audio list
  • toggle play
  • play next audio
  • play prev audio
  • play audio by custom play index
  • update play index
  • SortableJS methods
class App extends React.Component {
  constructor() {
    this.audioInstance = null
  }
  render() {
    return (
      <>
        <ReactMuOnMusicPlayer
          getAudioInstance={(instance) => {
            this.audioInstance = instance
          }}
        />
        <button onClick={() => this.audioInstance.play()}>play</button>
        <button onClick={() => this.audioInstance.pause()}>pause</button>
        <button onClick={() => this.audioInstance.load()}>reload</button>
        <button onClick={() => this.audioInstance.currentTime = 40}>
          change current play time
        </button>
        <button onClick={() => this.audioInstance.playbackRate = 2}>
          change play back rate
        </button>
        <button onClick={() => this.audioInstance.volume = 0.2}>
          change volume
        </button>
        <button onClick={() => this.audioInstance.destroy()}>
          destroy player
        </button>
        <button onClick={this.audio.togglePlay}>toggle play</button>
        <button onClick={this.audio.clear}>clear audio lists</button>
        <button onClick={this.audio.playNext}>play next</button>
        <button onClick={this.audio.playPrev}>play prev</button>
        <button onClick={() => this.audio.playByIndex(1)}>play by index</button>
        <button onClick={() => this.audio.updatePlayIndex(1)}>
          update play index
        </button>
      </>
    )
  }
}

:bulb: 흐린 배경

<ReactMuOnMusicPlayer glassBg />

:bulb: 커스텀 다운로더 구현

Default use downloadjs, you can use any download library

eg. https://www.npmjs.com/package/file-saver, or use download attribute

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()
}

;<ReactMuOnMusicPlayer
  audioLists={[{ src: 'a.mp3' }]}
  customDownloader={customDownloader}
/>

// use onBeforeAudioDownload
const onBeforeAudioDownload = () => {
  return Promise.resolve({
    src: '1.mp3',
  })
}

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

;<ReactMuOnMusicPlayer
  customDownloader={customDownloader}
  onBeforeAudioDownload={onBeforeAudioDownload}
/>

:bulb: 플레이어 제거

const onBeforeDestroy = (currentPlayId, audioLists, audioInfo) => {
  return new Promise((resolve, reject) => {
    // your custom validate
    if (window.confirm('Are you confirm destroy the player?')) {
      // if resolve, player destroyed
      resolve()
    } else {
      // if reject, skip.
      reject()
    }
  })
}

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

;<ReactMuOnMusicPlayer
  showDestroy
  onBeforeDestroy={onBeforeDestroy}
  onDestroyed={onDestroyed}
/>

:bulb: 미디어 세션

https://web.dev/media-session/

// 매우 쉽고 매우 간단해요!!!
<ReactMuOnMusicPlayer showMediaSession />

:bulb: 다국어 지원(i18n)

Version: 4.11.0

Source

import Locale from 'muon-next-music-player/lib/config/locale'
// Two languages are provided by default
// one of zh_CN | en_US | ko_KR
<ReactMuOnMusicPlayer locale={Locale.ko_KR}/>
// <ReactMuOnMusicPlayer locale={'en_US'}/>

// Custom override
const customLocale = {
  playModeText: {
    order: '',
    orderLoop: '',
    singleLoop: '',
    shufflePlay: ''
  },
  openText: '',
  closeText: '',
  emptyText: '',
  clickToPlayText: '',
  clickToPauseText: '',
  nextTrackText: '',
  previousTrackText: '',
  reloadText: '',
  volumeText: '',
  playListsText: '',
  toggleLyricText: '',
  toggleMiniModeText: '',
  destroyText: '',
  downloadText: '',
  lightThemeText: '',
  darkThemeText: '',
  switchThemeText: '',
  removeAudioListsText: '',
  controllerTitle: '',
  emptyLyricText: '',
  clickToDeleteText: (name) => ``,
  audioTitle: ''
  // audioTitle: (audioInfo) => ``
}

<ReactMuOnMusicPlayer locale={customLocale}/>

// Support partial override, auto merge

<ReactMuOnMusicPlayer locale={{ audioTitle: "xxx" }}/>

:bulb: 테마 커스터마이징

import ReactMuOnMusicPlayer from 'muon-next-music-player'
import 'muon-next-music-player/lib/styles/index.less'
@primary-color: #31c27c;
@default-color: #d9d9d9;
@bg-color: #f7f8fa;
@border-color: #d9d9d9;
@panel-bg-light: #fff;
@controller-bg-light: #fff;
@music-player-panel-height: 80px;
@lists-panel-width: 480px;
@lists-panel-height: 410px;
@lists-panel-item-bg: #40444b;
@lists-panel-item-bg-light: #fff;
@panel-header-height: 50px;
@panel-bg: rgba(0, 0, 0, 0.7);
@font-color: #444;
@player-width: 80px;
@player-height: @player-width;
@base-color: rgba(255, 255, 255, 0.6);
@common-animate-type: cubic-bezier(0.43, -0.1, 0.16, 1.1);
@common-animate-time: 350ms @common-animate-type;
@progress-load-bar-bg-color: rgba(0, 0, 0, 0.11);
@progress-load-bar-bg-color-light: rgba(0, 0, 0, 0.06);
@progress-bar-bg-color-light: rgba(0, 0, 0, 0.09);
@progress-bar-bg-color-dark: #fff;
@player-lyric-color: @primary-color;
@player-lyric-font-size: 36px;
@player-lyric-font-size-mobile: 16px;
@player-lyric-z-index: 999;

웹팩 커스터마이징

// webpack.config.js

module.exports = {
  rules: [{
    test: /\.less$/,
    use: [
      ...
      {
      loader: 'less-loader',
+     options: {
+       modifyVars: {
+         'primary-color': '#444',
+         // or
+         'hack': `true; @import "your-less-file-path.less";`, // Override with less file
+       },
+       javascriptEnabled: true,
+     },
    }],
  }],
}

less 파일 커스타마이징

@import 'muon-next-music-player/lib/styles/index.less';
@import 'your-theme-file.less';

:bulb: 오디오 재생시간(최대 길이) 커스터마이징

Default: by this.audio.duration, if cannot get current play audio's duration, you can customize to set.

<ReactMuOnMusicPlayer audioLists={[{
  ...
  duration: 100.00
}]} />

:bulb: 플레이어 아이콘 커스터마이징

export interface ReactMuOnMusicPlayerIcon {
  pause?: React.ReactNode | string
  play?: React.ReactNode | string
  destroy?: React.ReactNode | string
  close?: React.ReactNode | string
  delete?: React.ReactNode | string
  download?: React.ReactNode | string
  toggle?: React.ReactNode | string
  lyric?: React.ReactNode | string
  volume?: React.ReactNode | string
  mute?: React.ReactNode | string
  next?: React.ReactNode | string
  prev?: React.ReactNode | string
  playLists?: React.ReactNode | string
  reload?: React.ReactNode | string
  loop?: React.ReactNode | string
  order?: React.ReactNode | string
  orderLoop?: React.ReactNode | string
  shuffle?: React.ReactNode | string
  loading?: React.ReactNode | string
}

:bulb: 시스템 컬러에 맞춰 테마 변경

<ReactMuOnMusicPlayer theme="auto" />

auto-theme

:bulb: 플레이리스트 조용하게 업데이트

/**
 * Don't interrupt current playing state when audio list updated
 * eg. (A) is current playing...
 * [A,B] => [A,C,B]
 * [A,B] => [A,B,C]
 *
 * if (A) not in updated audio lists
 * [A,B] => [C]
 * (C) is playing
 */

function App() {
  const [audioLists, setAudioLists] = useState([
    { musicSrc: 'A' },
    { musicSrc: 'B' },
  ])

  useEffect(() => {
    setTimeout(() => {
      setAudioLists([{ musicSrc: 'A' }, { musicSrc: 'C' }, { musicSrc: 'B' }])
    }, 1000)
  }, [setAudioLists])

  return (
    <ReactMuOnMusicPlayer
      quietUpdate
      clearPriorAudioLists
      audioLists={audioLists}
    />
  )
}

:bulb: 브라우저에 불러오기

<!DOCTYPE html>
<html lang="en">
  <head>
    <link
      rel="stylesheet"
      href="https://unpkg.com/muon-next-music-player@10.0.2/assets/index.css"
    />
  </head>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://unpkg.com/react@16.13.1/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@16.13.1/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/muon-next-music-player@10.0.2/dist/muon-next-music-player.min.js"></script>
  <script>
    ReactDOM.render(
      React.createElement(ReactMuOnMusicPlayer),
      document.getElementById('root'),
    )
  </script>
</html>

:bulb: SSR(서버사이드 랜더링)

// components/Player.js
import React from 'react'
import ReactMuOnMusicPlayer from 'muon-next-music-player'
import styles from 'muon-next-music-player/assets/index.module.css'

export const Player = () => <ReactMuOnMusicPlayer />

// pages/_app.js
import dynamic from 'next/dynamic'
const PlayerWithNoSSR = dynamic(() => import('../components/Player'), {
  ssr: false,
})

:bulb: 모바일 미디어 쿼리 커스터마이징

eg. Use mobile UI on a iPad device

// Default '(max-width: 768px) and (orientation : portrait)'
<ReactMuOnMusicPlayer mobileMediaQuery="(max-width: 1024px)" />

:bulb: 오디오 볼륨 페이드인 및 페이드 아웃 처리

<ReactMuOnMusicPlayer volumeFade={{ fadeIn: 500, fadeOut: 500 }} />

:pencil: 개발방법

git clone https://github.com/mueslico/muon-next-music-player.git
yarn # npm install
yarn start # npm start
open `http://localhost:8084/`

:hourglass: 테스트 케이스

npm run test

:bulb: AudioListProps

Like This

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

:bulb: AudioInfo

Like This

interface ReactMuOnMusicPlayerAudioInfo {
  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
}