移动端音乐播放器系统的设计与实现

《移动端音乐播放器系统的设计与实现》

github源码地址: https://github.com/Brannua/H5-music-player

移动端音乐播放器系统的设计与实现_第1张图片
一、前言

  • 为了巩固所学专业知识, 加深对软件工程概念和其他技术知识的理解, 增强自身的实践本领, 我自己设计并实现了一款技术栈丰富但规模并不庞大的移动端音乐播放器,从设计到实现的过程如下所示。

二、系统需求分析

  1. 展示当前播放的音乐专辑图片并对背景进行高斯模糊

  2. 实现音乐的播放和暂停功能

  3. 实现音乐切换上一首和下一首的功能

  4. 实现音乐播放进度展示的功能

  5. 实现音乐进度条可拖动的功能

  6. 实现播放音乐列表的功能

三、系统概要设计

1.技术选型

  • HTML5、CSS3、JavaScript、Zepto.js、Gulp.js、Mock.js、Node.js、Koa2、Mongoose、MongoDB

2.开发工具

  • VSCode: 代码编写工具

  • Cmder: 命令行工具

  • Robo 3T: 数据库管理工具

  • Google Chrome: 用于系统调试和展示

3.系统架构设计 ( MVC )

  • 3-1.前端部分

    • 使用HTML和CSS技术进行页面的布局。使用JavaScript脚本语言提供和用户之间的交互效果。使用Zepto.js中的Ajax模块向后端数据接口发送网络请求以获取音乐数据,然后使用成功获取到的数据进行页面渲染,后端数据接口尚未完成的情况下使用Mock.js拦截Ajax网络请求模拟后端数据接口。使用Gulp.js对源代码以及资源文件进行打包压缩,Gulp.js也用于在开发环境下开启本地服务器并将前端部分运行在本地服务器。
  • 3-2.后端部分

    • 使用JavaScript语法和Node.js环境编写后端数据接口, 选用Koa2后端框架,Mongoose.js用于定义数据库中的数据模型和操作数据库。
  • 3-3.数据库: 选用key-value型数据库 MongoDB

四、系统详细设计

  • 4-1.前端编写方式设计:

    • 4-1-1.使用闭包私有化变量的方式进行模块化开发

    • 4-1-2.使用原型链编程的方式封装模块

    • 4-1-3.使用单对象编程的方式将所有模块集中于对象player

    • 4-1-4.将player挂载于浏览器全局对象window

  • 4-2.前端封装模块

    	window.player = {
    	  // 构造函数构造管理背景音乐的对象
    	  AudioManager.prototype: {
    	    play: fn,                 // 播放背景音乐
    	    pause: fn,                // 暂停背景音乐
    	    status: fn,               // 获取当前背景音乐的播放状态
    	    resetMusicSrc: fn,        // 重置背景音乐src
    	    jump: fn,                 // 更新背景音乐播放进度
    	  },
    	
    	  // 构造函数构造管理索引的对象
    	  IndexManager.prototype: {
    	    resetCurIndex: fn,        // 传参则重置索引值并返回最新索引值,不传参则直接返回当前索引值
    	    prev: fn,                 // 当前索引值减一并置为最新索引
    	    next: fn,                 // 当前索引值加一并置为最新索引
    	    chooseListToSetIndex: fn, // 为了实现音乐列表功能中可以选中某个音乐来播放而增加
    	  },
    	
    	  // 构造函数构造管理音乐播放进度的对象
    	  ProgressManager.prototype: {
    	    refreshProgress: fn,      // 更新当前的播放进度
    	    pauseProgress: fn,        // 暂停当前的播放进度
    	    resetProgress: fn,        // 重置播放进度
    	  },
    	
    	  // 音乐播放列表模块
    	  Playlist: {
    	    renderPlaylist,           // 渲染音乐播放列表
    	    showPlaylist,             // 弹出播放列表
    	    hidePlaylist,             // 隐藏播放列表
    	  },
    	  render: fn,                 // 渲染页面
    	}
    
  • 4-3.适配不同移动端屏幕尺寸的方案

    • 4-3-1.将所有元素基础样式重置

    • 4-3-2.采用CSS3单位vh,vw

    • 4-3-3.采用em/rem布局

    • 4-3-4.采用百分比%布局

    • 4-3-5.采用flex布局

    • 4-3-6.歌曲名称过长则打点显示

        .song-name {
          text-overflow: ellipsis;
          overflow: hidden;zongjie
          white-space: nowrap;
        }
      
    • 4-3-7专辑封面保持正方形且自适应屏幕大小 , 所以专辑封面的html结构多嵌套了一层div

      • 设置height为0后padding-top或padding-bottom会自动寻找父级宽度

      • 由于.song-img的height为0 , 故.img-wrapper无法使用height: 100%撑开元素 , 故采用定位的方式撑开元素

            .song-img {
              width: 50%;
              height: 0;
              padding-top: 50%;
              position: relative;
              .img-wrapper {
                position: absolute;
                top: 0;
                bottom: 0;
                left: 0;
                right: 0;
              }
            }
        
  • 4-4.播放进度的刷新使用H5动画API-requestAnimationFrame

    • 4-4-1.无需手动计算回调时间,动画的流畅性更有保障。
    • 4-4-2.性能优秀,占用内存少,对隐藏或者不可见元素的动画,requestAnimationFrame不会进行重绘或回流。
  • 4-5.后端部分( 使用Koa2快速搭建 )

    • 4-5-1.项目运行于本地时的数据接口: http://localhost:3000/api/getMusicList

    • 4-5-2.前后端跨域解决方案

      • 由于前端运行在Gulp.js运行的本地服务器,后端运行在Koa.js运行的本地服务器,二者监听的端口号不相同,造成了前后端通信发生的跨域拦截请求,我采用Koa提供的中间件koa-cors在后端进行了配置成功解决跨域问题
    • 4-5-3.数据库数据建模

      	// 音乐数据模型
      	new Schema({
      	  musicId: Schema.Types.ObjectId,
      	  image: String,
      	  audio: String,
      	  song: String,
      	  album: String,
      	  singer: String,
      	  duration: Number,
      	  isLike: Boolean,
      	})
      

代码优化

progressManager.js 模块中借鉴使用了函数节流的思想

  • 每当触发播放事件

    • 调用H5动画API

    • 首帧保存住时间戳

    • 往后每一帧与该时间戳之差取整

    • 一旦为1 , 则累加到当前播放时间并判断是否播放完

    • 未播放完则将累加结果赋给当前播放时间

    • 并将保存住的时间戳更新为本帧时间戳

    • 播放完则cancelAnimationFrame

  • 一旦暂停事件触发则cancelAnimationFrame

开发依赖[email protected]

  • gulp基于任务 , 任务基于事件 , 如下是任务的触发顺序示例

        var gulp = require('gulp')
      
        // 先触发task2任务然后触发task1任务然后执行回调函数
        gulp.task('task1', ['task2'], function () {})
      
        // 先触发task1任务然后触发default任务
        gulp.task('default', ['task1'])
    
  • gulpfile.js : gulp的配置文件

    • 基于4个api将src下的文件转移到dist文件夹

    • 配置起一个服务器

      • 使用gulp-connect插件 : npm install gulp-connect --save-dev
    • 配置打包less为css至dist

      • 使用gulp-less插件 : npm install gulp-less --save-dev

      • 浏览器打开项目f12报错Refused to apply style : 因为项目在服务器上运行的是dist目录 , 相对路径的引入要按照dist文件夹中的编译结果来写

            // before handle bug
            <link rel="stylesheet" href="./css/index.less">
            // bug handled
            <link rel="stylesheet" href="./css/index.css">
        

结论

  • 通过本次的系统设计与实现练习,我成功实现了所有基础功能,对以往的知识点有了更深层次的理解,提高了自己的技术水平,也认识到了自己的不足之处,我会继续努力,不骄不馁。

你可能感兴趣的:(移动端音乐播放器系统的设计与实现)