• Django实现音乐网站 (22)


    使用Python Django框架做一个音乐网站

    本篇音乐播放器功能完善:顺序播放、设置播放数、歌词滚动等功能。

    目录

    顺序播放

    设置顺序播放

    单曲播放数

    添加路由

    视图处理

    模板处理

    歌词滚动

    视图内容返回修改

    样式设置

    模板内容

    歌词滚动脚本

    歌词滚动判断

    模板设置

    播放器脚本修改

    设置音乐

    播放器初始化修改

    歌曲详情修改

    借鉴博客

    项目源码

    项目目录结构

    说明

    下载地址

    总结


    顺序播放

    当播放完一首歌曲后,继续播放下一首,循环播放列表中的单曲。

    实践发现使用audio媒体的loop属性只是对当前的单曲的循环播放。

    需自定义实现循环播放功能。

    设置顺序播放

    通过监听播放器结束事件,设置触发播放下一曲。

    脚本内容如下:

    1. $player.addEventListener('ended', function () {
    2. if (currentIndex < (music_list.length - 1)) {
    3. currentIndex += 1;
    4. } else {
    5. // 切换为第一首
    6. currentIndex = 0;
    7. }
    8. // 设置播放标识为暂停
    9. $dian.className = 'glyphicon glyphicon-play';
    10. // 播放时间
    11. $('.playTimeSpan').text('00:00');
    12. // 设置歌曲进度归零
    13. $('.music-progress').css('width', '1px');
    14. // 设置歌曲
    15. setMusic();
    16. // 同步播放列表状态
    17. var nowDiv = $("#play_list").children('.active_cur');
    18. nowDiv.find('.playing').hide();
    19. nowDiv.removeClass('active_cur');
    20. var newDiv = $("#music_num"+(currentIndex+1));
    21. newDiv.addClass('active_cur');
    22. newDiv.find('.playing').show();
    23. // 设置播放器 播放状态
    24. var music_dian = $('#music_dian');
    25. if (music_dian.attr('class') == 'glyphicon glyphicon-play') {
    26. music_dian.attr('class', 'glyphicon glyphicon-pause');
    27. }
    28. $player.play();
    29. });

    单曲播放数

    在歌曲播放时,增加歌曲播放数功能;在排行榜中需要播放数进行排序。

    添加路由

    1. # 增加播放数
    2. path('add_play_num', views.add_play_num, name='add_play_num'),

    视图处理

    通过模板传递的单曲id,查询单曲记录;

    如果存在:即在原来基础上增加1;

    最后返回状态并做json处理。

    内容如下:

    1. def add_play_num(request):
    2. """ 增加单曲播放量 """
    3. id = request.GET.get('id')
    4. info = Singe.objects.filter(pk=id).first()
    5. if info:
    6. info.playnum += 1
    7. info.save()
    8. return JsonResponse({'status': 1, 'msg': '操作成功!'})

    模板处理

    对audio媒体监听播放事件时,获取当前播放歌曲的单曲id,传递给视图进行处理。

    内容如下:

    1. // 监听播放器 播放时触发
    2. $player.addEventListener('play', function () {
    3. // 处理同步播放列表 播放状态
    4. $("#music_num"+currentIndex).removeClass('active_cur');
    5. $("#music_num"+currentIndex).find('.playing').hide();
    6. $("#music_num"+(currentIndex+1)).addClass('active_cur');
    7. $("#music_num"+(currentIndex+1)).find('.playing').show();
    8. // 增加单曲播放数
    9. $. get('/add_play_num', {'id':music_list[currentIndex].song_id}, function (msg) {
    10. if(msg.status == 1) {
    11. layer.msg(msg.msg, {icon: 6});
    12. } else {
    13. layer.msg(msg.msg, {icon: 5});
    14. }
    15. });
    16. });

    效果:

    歌词滚动

    在歌曲详情中播放音乐时,歌词与播放进度同步滚动显示。

    视图内容返回修改

    原来的视图中歌词处理为列表了,现在只需要通过join函数连接为文本即可。

    内容如下:

    1. def album_song(request):
    2. """ 专辑中单曲详情 """
    3. sid = request.GET.get('sid')
    4. song_info = Singe.objects.filter(id=sid).first()
    5. # 反向查询专辑
    6. info = song_info.album_set.first()
    7. # 歌词处理
    8. lyrics = []
    9. if song_info:
    10. lyrics = read_lyric(song_info.lyric)
    11. lyric_text = "".join(lyrics)
    12. return render(request, 'album/song.html', locals())
    13. def read_lyric(path):
    14. """ 读取歌词文件 """
    15. f = open(os.path.join(settings.MEDIA_ROOT, str(path)), 'r', encoding='utf-8')
    16. lines = []
    17. for line in f:
    18. lines.append(line)
    19. f.close()
    20. return lines

    样式设置

    设置歌词滚动功能所需的样式。

    内容如下:

    1. .bg {
    2. /* 歌词调整区 */
    3. width: 100%;
    4. /* 歌词显示盒子宽 */
    5. height: 200px;
    6. /* 歌词显示盒子高度,需要多显示几行歌词相应调大即可 */
    7. /* background-color:#333; */
    8. /* 歌词背景颜色 */
    9. margin: 15px auto;
    10. color: darkgrey;
    11. /* 歌词默认颜色,灰色 */
    12. font-size: 15px; /* 歌词字体默认大小 */
    13. overflow: hidden;
    14. position: relative;
    15. font-family: "宋体"; /*字体可以随便换*/
    16. }
    17. .bg ul {
    18. width: 100%;
    19. position: absolute;
    20. top: 0;
    21. left: 0;
    22. list-style: none;
    23. }
    24. .bg ul li {
    25. width: 100%;
    26. height: 30px;
    27. line-height: 30px;
    28. text-align: left;
    29. }
    30. .bg ul li.active { /* 歌词高亮滚动区 */
    31. color: #ffe12c;
    32. font-size: 18px;
    33. }

    模板内容

    把歌词文本放入一个隐藏输入框中及设定歌词渲染的元素。

    内容如下:

    1. <input type="hidden" id="text" value="{{lyric_text}}">
    2. <div class="lyric lyricAll bg">div>

    歌词滚动脚本

    歌词滚动效果,用的网上的文章内容做的,能够实现滚动;

    就是有两个问题:

    1.播放进度与显示进度不符。

    2.滚动的速度太快了,歌词显示选中的都已经卷过了。

    之后有时间就调试一下,这两个问题归根其实是一个问题,播放进度与显示进度不符。

    分割歌词、歌曲进度计算、设置卷动速度都调了一遍,发现没问题。

    最后发现设置元素这里有问题,给ul、li分别设置了id、class完美实现歌词滚动。

    脚本内容如下:

    1. $(function() {
    2. function parseLyric(text) {
    3. //按行分割歌词
    4. let lyricArr = text.split('\n');
    5. let result = []; //新建一个数组存放最后结果
    6. // 遍历分割后的歌词数组,将格式化后的时间节点,歌词填充到result数组
    7. for (i = 0; i < lyricArr.length; i++) {
    8. let playTimeArr = lyricArr[i].match(/\[\d{2}:\d{2}((\.|\:)\d{2})\]/g); //正则匹配播放时间
    9. let lineLyric = "";
    10. if (lyricArr[i].split(playTimeArr).length > 0) {
    11. lineLyric = lyricArr[i].split(playTimeArr);
    12. }
    13. if (playTimeArr != null) {
    14. for (let j = 0; j < playTimeArr.length; j++) {
    15. let time = playTimeArr[j].substring(1, playTimeArr[j].indexOf("]")).split(":");
    16. // 数组填充
    17. result.push({
    18. time: (parseInt(time[0]) * 60 + parseFloat(time[1])).toFixed(4),
    19. content: String(lineLyric).substr(1)
    20. });
    21. }
    22. }
    23. }
    24. return result;
    25. }
    26. // 这里请按照格式放入相应歌词--开始
    27. let text = $('#text').val();
    28. // 这里请按照格式放入相应歌词--结束
    29. let audio = document.querySelector('audio');
    30. // 执行lyc解析
    31. let result = parseLyric(text);
    32. // 把生成的数据显示到界面上去
    33. let $ul = $("
        "
        );
      • for (let i = 0; i < result.length; i++) {
      • let $li = $("
      • ").text(result[i].content);
    34. $ul.append($li);
    35. }
    36. $(".bg").append($ul);
    37. // 当前行歌词
    38. let lineNo = 0;
    39. // 当播放6行后开始滚动歌词
    40. let preLine = 1;
    41. // 每次滚动的距离
    42. let lineHeight = -30;
    43. // 滚动播放 歌词高亮 增加类名active
    44. function highLight() {
    45. let $li = $(".ld");
    46. $li.eq(lineNo).addClass("active").siblings().removeClass("active");
    47. if (lineNo > preLine) {
    48. $ul.stop(true, true).animate({ top: (lineNo - preLine) * lineHeight });
    49. }
    50. }
    51. highLight();
    52. // 播放的时候不断渲染
    53. audio.addEventListener("timeupdate", function() {
    54. if (lineNo == result.length) return;
    55. if ($(".ld").eq(0).hasClass("active")) {
    56. $("#ly").css("top", "0");
    57. }
    58. lineNo = getLineNo(audio.currentTime);
    59. highLight();
    60. lineNo++;
    61. });
    62. // 当快进或者倒退的时候,找到最近的后面那个result[i].time
    63. function getLineNo(currentTime) {
    64. if (currentTime >= parseFloat(result[lineNo].time)) {
    65. // 快进
    66. for (let i = result.length - 1; i >= lineNo; i--) {
    67. if (currentTime >= parseFloat(result[i].time)) {
    68. return i;
    69. }
    70. }
    71. } else {
    72. // 后退
    73. for (let i = 0; i <= lineNo; i++) {
    74. if (currentTime <= parseFloat(result[i].time)) {
    75. return i - 1;
    76. }
    77. }
    78. }
    79. }
    80. // 播放结束自动回到开头
    81. audio.addEventListener("ended", function() {
    82. lineNo = 0;
    83. highLight();
    84. audio.play();
    85. $("#ly").css("top", "0");
    86. });
    87. });
    88. 效果:

      歌词滚动判断

      增加歌词滚动判断是否为播放当前音乐;因为歌词滚动功能在歌曲详情实现的,如果不加判断,在播放歌曲时,查看另外一首歌曲的详情也会滚动。

      模板设置

      在设置音乐播放的盒子中,增加一个隐藏输入框,

      用来设置当前播放音乐的id,用以歌词滚动判断。

      内容如下:

      1. <div class="play_left">
      2. <div class="music_title">
      3. <span class="music_name">七里香 – 周杰伦span>
      4. <span class="totalTimeSpan">/04:59span>
      5. <span class="playTimeSpan">00:00span>
      6. <input type="hidden" id="now_music" value="0">
      7. div>
      8. <div class="music_rate">
      9. <div class="music-progress">div>
      10. div>
      11. div>

      播放器脚本修改

      设置音乐

      在音乐播放器play.js中设置音乐的方法中,增加设置隐藏输入框当前音乐id.

      内容如下:

      1. // 设置播放器歌曲信息
      2. function setMusic() {
      3. // 设定歌曲封面
      4. $('#music_img').attr('src', music_list[currentIndex].cover);
      5. // 设定歌曲名称和歌手
      6. $('.music_name').text(music_list[currentIndex].song_name +
      7. ' - ' + music_list[currentIndex].singer);
      8. // 设定歌曲路径
      9. $player.src = music_list[currentIndex].song_path;
      10. // 设置当前播放音乐id
      11. $('.now_music').val(music_list[currentIndex].song_id);
      12. }

      播放器初始化修改

      需要在播放器初始化方法中也增加设置。

      内容如下:

      $('#now_music').val(music_list[currentIndex].song_id);

      歌曲详情修改

      在歌曲详情歌词滚动脚本中增加判断是否为当前播放音乐。

      原来脚本内容的基础上,在歌词渲染完毕之后,

      增加三行内容判断是否为播放当前音乐,

      如果不是,则终止向下执行。

      内容如下:

      1. // 把生成的数据显示到界面上去
      2. let $ul = $("
          "
          );
        • for (let i = 0; i < result.length; i++) {
        • let $li = $("
        • ").text(result[i].content);
    89. $ul.append($li);
    90. }
    91. $(".bg").append($ul);
    92. // 判断播放音乐是否为当前页音乐
    93. let now_music = $('#now_music').val();
    94. let page_music = "{{song_info.id}}";
    95. if(now_music != page_music) return;
    96. 借鉴博客

      html页面制作滚动歌词_网页版动态歌词-CSDN博客

      项目源码

      如果觉得通过文章讲解不直观或者还是有些不懂的,

      可以下载源码再针对某方面内容仔细查看。

      项目目录结构

      说明

      Media:前端和后台上传文件媒体目录

      myMusic:项目工程目录

      Player:项目子应用目录

      Static:项目静态文件存储目录

      Templates:应用模板路径

      Mymusic.sql 音乐网站数据库表文件

      下载地址

      链接:百度网盘 请输入提取码

      提取码:13lq

      总结

      本篇还是播放器功能完善,主要实现功能为:

      播放列表顺序播放;添加单曲播放数;播放时歌词滚动等功能实现。

    97. 相关阅读:
      OpenSSH升级版本(7.4升级到8.9)
      不知道吧?未加工的食物可以帮助你减肥
      SpringBoot笔记梳理
      Thymeleaf学习(2)—— 流程控制
      准备pmp考试第13天
      MYSQL——分组
      5G智能网关如何解决城市停车痛点难点
      【IntelliJ IDEA】切换jdk版本配置
      腾讯云服务器竞价实例是什么意思?
      数据中台建设模式的4大趋势和3大重点总结全了
    98. 原文地址:https://blog.csdn.net/json_ligege/article/details/133982635