今天我们做歌曲的单曲循环,按序播放,随机播放以及通过手动点击上一首,下一首这些功能哈,下一篇博客就写我们歌词滚动功能

由于我每篇都和前面是联系在一起的,如果想获取整个项目,可以去我的github下载源码

首先到我们的组件中,分三步来写(之前的逻辑我没删除)

第一步,导入的配置

import React, { memo, useState, useEffect, useRef, useCallback } from 'react';
import { useDispatch, useSelector, shallowEqual } from 'react-redux';import { getSizeImage, formatDate, getPlaySong } from '@/utils/format-utils';import { NavLink } from 'react-router-dom';
import { Slider,message } from 'antd';import { getSongDetailAction,changeSequenceAction,changeCurrentIndexAndSongAction,changeCurrentLyricIndexAction } from '../store/actionCreators';
import {PlaybarWrapper,Control,PlayInfo,Operator
} from './style';

这些就没必要说了

第二步,我们的逻辑代码

 // props and stateconst [currentTime, setCurrentTime] = useState(0);const [progress, setProgress] = useState(0);const [isChanging, setIsChanging] = useState(false);const [isPlaying, setIsPlaying] = useState(false);const [showPanel, setShowPanel] = useState(false);// redux hookconst { currentSong,sequence,playList,lyricList,currentLyricIndex } = useSelector(state => ({playList:state.getIn(["player","playList"]),currentSong: state.getIn(["player", "currentSong"]),sequence: state.getIn(["player", "sequence"]),lyricList: state.getIn(["player", "lyricList"]),currentLyricIndex: state.getIn(["player", "currentLyricIndex"])}), shallowEqual);const dispatch = useDispatch();// other hooksconst audioRef = useRef();useEffect(() => {dispatch(getSongDetailAction(167876));}, [dispatch]);useEffect(() =>  {audioRef.current.src = getPlaySong(currentSong.id);audioRef.current.play().then(res => {setIsPlaying(true);}).catch(err => {setIsPlaying(false);});}, [currentSong]);// other handleconst picUrl = (currentSong.al && currentSong.al.picUrl) || "";const singerName = (currentSong.ar && currentSong.ar[0].name) || "未知歌手";const duration = currentSong.dt || 0;const showDuration = formatDate(duration, "mm:ss");const showCurrentTime = formatDate(currentTime, "mm:ss");// handle functionconst playMusic = useCallback(() => {isPlaying ? audioRef.current.pause(): audioRef.current.play();setIsPlaying(!isPlaying);},[isPlaying])const timeUpdate = (e) => {const currentTime = e.target.currentTime;if (!isChanging) {setCurrentTime(e.target.currentTime * 1000);setProgress(currentTime * 1000 / duration * 100);}}//变换0,1,2,循环,单曲等const changeSequence = () => {let currentSequence = sequence + 1;if (currentSequence > 2) {currentSequence = 0;}dispatch(changeSequenceAction(currentSequence));}//上一首,下一首const changeMusic = (tag) => {dispatch(changeCurrentIndexAndSongAction(tag));}//歌曲播放完之后const handleMusicEnded = () => {if (sequence === 2) { // 单曲循环audioRef.current.currentTime = 0;audioRef.current.play();} else {dispatch(changeCurrentIndexAndSongAction(1));}}//useCallback:当把一个回调函数传到一个自定义组件内部时候用const sliderChange = useCallback((value) => {setIsChanging(true);const currentTime = value / 100 * duration;setCurrentTime(currentTime);setProgress(value);}, [duration]);const sliderAfterChange = useCallback((value) => {const currentTime = value / 100 * duration / 1000;audioRef.current.currentTime = currentTime;setCurrentTime(currentTime * 1000);setIsChanging(false);if (!isPlaying) {playMusic();}}, [duration,isPlaying, playMusic]);

我就说一下,跟我们这个demo有关的一些

 //变换0,1,2,循环,单曲等const changeSequence = () => {let currentSequence = sequence + 1;if (currentSequence > 2) {currentSequence = 0;}dispatch(changeSequenceAction(currentSequence));}//上一首,下一首const changeMusic = (tag) => {dispatch(changeCurrentIndexAndSongAction(tag));}//歌曲播放完之后const handleMusicEnded = () => {if (sequence === 2) { // 单曲循环audioRef.current.currentTime = 0;audioRef.current.play();} else {dispatch(changeCurrentIndexAndSongAction(1));}}

我们在redux里面定义了一个变量sequence

sequence: 0, // 0 循环 1 随机 2 单曲

解析:

changeSequence点击事件:我们初始化是0,也就是最开始的时候是根据列表顺序循环,点击一次就+1,也就是成随机循环了,依次类推三个循环,再通过dispatch改变我们redux里面的sequence

store里面

reducer.js

import { Map } from 'immutable';import * as actionTypes from './constants';const defaultState = Map({sequence: 0, // 0 循环 1 随机 2 单曲
});function reducer(state = defaultState, action) {switch(action.type) {case actionTypes.CHANGE_SEQUENCE:return state.set("sequence", action.sequence);default:return state;}
}export default reducer;

constants.js

export const CHANGE_SEQUENCE = "player/CHANGE_SEQUENCE";

actionCreators.js

export const changeSequenceAction = (sequence) => ({type: actionTypes.CHANGE_SEQUENCE,sequence
});

然后回到我的们组件

  //上一首,下一首const changeMusic = (tag) => {dispatch(changeCurrentIndexAndSongAction(tag));}

解析

这两个button,第一个点击就是上一首,第二个下一首

<button className="sprite_player prev" onClick={e => changeMusic(-1)}></button><button className="sprite_player next" onClick={e => changeMusic(1)}></button>通过点击事件再发送一个dispatch,changeCurrentIndexAndSongAction把tag传过去

到我们的actionCreators.js

export const changeCurrentIndexAndSongAction = (tag) =>{return (dispatch, getState) => {const playList = getState().getIn(["player", "playList"]);const sequence = getState().getIn(["player", "sequence"]);let currentSongIndex = getState().getIn(["player", "currentSongIndex"]);switch (sequence) {case 1:let randomIndex = getRandomNumber(playList.length);while (randomIndex === currentSongIndex) {randomIndex = getRandomNumber(playList.length);}currentSongIndex = randomIndex;break;default: currentSongIndex += tag;if (currentSongIndex >= playList.length) currentSongIndex = 0;if (currentSongIndex < 0) currentSongIndex = playList.length - 1;}const currentSong = playList[currentSongIndex];dispatch(changeCurrentSongAction(currentSong));dispatch(changeCurrentSongIndexAction(currentSongIndex));}
}

解析1

先获取到我们的playList,这个是我们的歌曲数组,sequence哪个状态,currentSongIndex是歌曲的下标,也是在redux中定义的

解析2

先通过判断sequence是多少,随机播放,这个地方需要一个随机数

getRandomNumber

export function getRandomNumber(num) {return Math.floor(Math.random() * num);
}

然后是这个

  //歌曲播放完之后const handleMusicEnded = () => {if (sequence === 2) { // 单曲循环audioRef.current.currentTime = 0;audioRef.current.play();} else {dispatch(changeCurrentIndexAndSongAction(1));}}

解析:

当我们不点击,等歌曲播放完之后,这个要根据我们选定点哪种状态,是循环,随机还是啥的来进行下一步

<audio  onEnded={e => handleMusicEnded()}/>

总的来说,跟前面几篇博客关系都太紧密了,可能分开后,有些没有写好,如果有不懂的可以去我github下载源码来进行学习

github项目地址:https://github.com/lsh555/WYY-Music

React实现(Web端)网易云音乐项目(五),错过了真的可惜呀相关推荐

  1. React实现(Web端)网易云音乐项目(一),错过了真的可惜呀

    首先肯定是搭建项目的结构了,通过脚手架安装这部分我就不说了 首先看项目的目录结构 assets:放我们的静态资源,图片,字体和公共初始样式等 common:放我们公共的JS文件 components: ...

  2. React实现(Web端)网易云音乐项目(三),错过了真的可惜呀

    接着前面的继续写了,这篇博客就写这两个页面,下一篇就主要讲歌曲播放功能,进度条拉伸以及歌曲时间的变化了 先完成新碟上架Demo 一.第一步不用说肯定是先获取我们这个数据对吧 去到我们services文 ...

  3. React实现(Web端)网易云音乐项目(四),错过了真的可惜呀

    今天就写一下歌曲播放这个功能,进度条拉伸以及歌曲时间的变化,当我们改变一个状态的时候,其他几个都相应改变,这个功能还是有一点复杂的- 就是这个,当我们可以播放,暂停,当我们播放的时候,进度条改变以及歌 ...

  4. React实现(Web端)网易云音乐项目(六),错过了真的可惜呀

    今天实现歌曲播放时,歌词随着滚动的效果 网易云原本的歌词是这样的 [00:00.000] 作曲 : 许嵩 [00:01.000] 作词 : 许嵩 [00:22.240]天空好想下雨 [00:24.38 ...

  5. React实现(Web端)网易云音乐项目(二),错过了真的可惜呀

    接着上一篇来继续写了,这篇博客主要完成下面这部分 一.首先先完成这个轮播图了,那肯定需要请求数据了,所以我们先把网络请求部分先写好 在React里面我们也是通过axios来发送网络请求的,先安装 ya ...

  6. PC端网易云音乐播放云盘音乐时显示加载失败,自动调转下一首的解决方法

    PC端网易云音乐播放云盘音乐时显示加载失败,自动调转下一首解决方法 注意: 一定要看看是不是和你的情况一样,不一样不要用这种方法!!! 具体情况: 我们经常会下载歌曲存到电脑文件夹里,然后通过网易云音 ...

  7. angular8 | 网易云音乐项目实战(一)

    angular8 网易云音乐项目实战(一) 视频教程原地址:https://www.bilibili.com/video/av70355308 本文为学习笔记 从github上clone相关源码 cs ...

  8. 微信小程序之网易云音乐(五)- 排行详情页、歌单详情页、播放器组件开发

    微信小程序之网易云音乐(五)- 排行详情页.歌单详情页.播放器组件开发 一. 排行详情页模块 二. 歌单详情页模块 三. 播放器组件 微信小程序之网易云音乐导航 一. 排行详情页模块 rank.vue ...

  9. Vue2 - 网易云音乐项目笔记(基于Vant UI组件库)

    目录 一.项目技术 二.准备工作 1.初始化Vue项目 2.配置Vant UI组件库 3.下载并使用vue-router库 4.接口API 5.postcss插件 三.分析页面实现功能 1.路由页面准 ...

最新文章

  1. SQL语言 之 数据查询
  2. Spring-国际化信息03-容器级的国际化信息资源
  3. 棋牌游戏服务器架构: 总体设计
  4. stm32 火灾自动报警及联动控制源码_中级消防设施操作员关键技能之十四:能测试火灾自动报警系统联动功能...
  5. 终端打开后-bash_如何爵士化Bash终端-带有图片的分步指南
  6. springcloud使用feign进行远程服务调用
  7. SpringBoot + SpringBatch + Quartz整合定时批量任务
  8. PHP 的 Git 服务器被黑客入侵,源码库将永久迁移至 GitHub!
  9. 怎么看so文件是哪个aar引进来的_运城人才引进7月5号面试
  10. Oracle 11gR2数据库使用
  11. vlan网络隔离实验
  12. 【Fortran】CUDA+PGI Fortran安装教程
  13. 计算机辅助汽车人机工程未来挑战,计算机辅助人机工程设计的虚拟人分析-机械制造及其自动化专业论文.docx...
  14. 无痛学习ISAC(三)
  15. node.js 上传文件比较 busboy vs. formidable vs. multer vs. multiparty
  16. 怎么利用计算机求一元三次方程,一元三次方程怎么快速把解求出来?
  17. 机器人学习-matlab四足机器人控制仿真
  18. 系统提供人民币(CNY)美元(USD)英镑(GBP)价值转换
  19. C1任务01-植物大战僵尸修改游戏存档(小白也能看懂)
  20. android 通知静音_如何使电话静音(但不包括短信和通知)

热门文章

  1. wxPython的安装
  2. 3dmax动画学习阶段总结
  3. 集合——Collections
  4. 去除nginx.conf文件中注释和空格行方法
  5. 防火墙设计和部署解析
  6. 方差、标准差、平方差、残差
  7. Windows server 2012 R2系统怎么安装IIS管理器?
  8. 什么是DAS、NAS、SAN、IP-SAN,它们之间有什么区别?
  9. (笔记)神经网络压缩,Ristretto: Hardware-Oriented Approximation of Convolutional Neural Networks(一)
  10. 企业为什么要大力推进OA办公?