Project preview

Code address: github.com/hcm083214/a…

Music player

  • Playback controls
  • Play progress bar control
  • Lyrics display and highlight
  • Play Mode Setting

Player attributes classification

Attributes and DOM elements of players are classified according to their functions. Elements and attributes that implement the same function are stored in the same object for easy management and operation

const control = { // Store the player control
    play: document.querySelector('#myplay'),...index: 2.// The number of the current song. }const audioFile = { // Store song files and related information
    file: document.getElementsByTagName('audio') [0].currentTime: 0.duration: 0,}const lyric = { // Lyrics display bar configuration
    ele: null.totalLyricRows: 0.currentRows: 0.rowsHeight: 0,}const modeControl = { // Play mode
    mode: ['order'.'random'.'single'].index: 0
}

const songInfo = { // The DOM container that holds the song information
    name: document.querySelector('.song-name'),... }Copy the code

Playback controls

Function: control music play and pause, last, next, play complete and corresponding icon modification

Audio: Audio. Play () and audio. Pause () and Audio ended events

// Play and pause music, previous track, next track control
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 music, change icon and enable play animation
        play.classList.remove('songStop');
        play.classList.add('songStart');
        control.albumCover.classList.add('albumRotate');
        control.albumCover.style.animationPlayState = 'running';
    } else {
        // Pause the music, change the icon and pause the animation. }}function prevHandle() {    // Reload the song according to the playback mode
    const modeIndex = modeControl.index;
    const songListLens = songList.length;
    if (modeIndex == 0) {// Play in sequence
        let index = --control.index;
        index == -1 ? (index = songListLens - 1) : index;
        control.index = index % songListLens;
    } else if (modeIndex == 1) {// Random play
        const randomNum = Math.random() * (songListLens - 1);
        control.index = Math.round(randomNum);
    } else if (modeIndex == 2) {/ / single
    }
    reload(songList);
}

function nextHandle() {
    const modeIndex = modeControl.index;
    const songListLens = songList.length;
    if (modeIndex == 0) {// Play in sequence
        control.index = ++control.index % songListLens;
    } else if (modeIndex == 1) {// Random play
        const randomNum = Math.random() * (songListLens - 1);
        control.index = Math.round(randomNum);
    } else if (modeIndex == 2) {/ / single
    }
    reload(songList);
}
Copy the code

Play progress bar control

Function: Update the playing progress in real time, click the progress bar to adjust the song playing progress

Audio API used: Audio timeUpdate event, audio. CurrentTime

// Play real-time progress update
audioFile.file.addEventListener('timeupdate', lyricAndProgressMove);
// Adjust the progress by dragging and dropping
control.progressDot.addEventListener('click', adjustProgressByDrag);
// Adjust the progress by clicking
control.progressWrap.addEventListener('click', adjustProgressByClick);
Copy the code

Real-time update of playback progress: By modifying the position or width of the corresponding DOM element

function lyricAndProgressMove() {
    const audio = audioFile.file;
    const controlIndex = control.index;
	// The song information is initialized
    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);

    // Progress bar moves
    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);

}
Copy the code

Drag and drop to adjust the progress: Move the progress bar by dragging and dropping, and update the song playing progress synchronously

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'.() = > { // Drag and drop
        // Click to enlarge for easy operation
        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) { // Progress bar status update
    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}% `
}
Copy the code

Click the progress bar to adjust: Click the progress bar and synchronize the song playing progress

function adjustProgressByClick(e) {

    const wrap = control.progressWrap;
    const wrapWidth = wrap.offsetWidth;
    const wrapLeft = getOffsetLeft(wrap);
    const disX = e.pageX - wrapLeft;
    changeProgressBarPos(disX, wrapWidth)
}
Copy the code

Lyrics display and highlight

Function: Update lyrics display in real time according to playback progress, and highlight current lyrics (by adding styles)

Audio API used: Audio timeUpdate event, audio. CurrentTime

// Lyrics display real-time updates
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;
    // Lyrics move
    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)}`)}}})}Copy the code

Play Mode Setting

Function: Click jump play mode, and modify the corresponding icon

Audio API used: None

// Set the playback mode
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")}Copy the code