实现一个网易云音乐

RT实现一个可以在线播放的移动端网易云音乐。

tips:网易云音乐没用响应式,因为它做了两套网站。用户使用的PC端时,域名为http://music.163.com/;使用移动端时,域名为http://music.163.com/m/

实现一个网易云音乐_第1张图片
根据用户设备自动跳转相匹配页面,不是响应式
PC端和手机端的区别
  • 屏幕不一样大
    PC端投放广告的数量,有很多选择主要用来放广告
    手机端界面小,不能乱放广告,放太多广告影响用户体验,点不到内容。
  • 触屏
    手机端可以触屏
    补充:现在PC端也有可以触屏的,如微软surface pro5
  • 没有IE
    手机端没有IE,可以兼容css3
  • 手机端省掉一些标签
    比如没有hover。

实现一个网易云音乐_第2张图片
界面

开始

  • 创建文件夹
  mkdir music-demo
  • 变为git仓库
  git init
  //生成.git目录
  • 初始化一下仓库
  npm init  //回车到结束
  //生成package.json文件
  • 上传到本地库
  git add .
  git commit -v   ==> init
  • git文章
    Git学习

编写网页

  • 创建页面
  touch home.html  playlist.html song.html
  // 创建首页  歌单页面  播放页面
  • 上传到本地仓库
  git add .
  git commit -v ==> add pages
  
  commit查看记录
  git log
  git show [commit字符串]  //查看修改代码 
  • 使用jQuery
  npm i jquery --save
  //安装到node_modules文件中
  使用ll node-modules/ 可以查看里面的文件
  包有jquery,就对了
  • 上传到本地库
  git add .
  git commit -v ==> install jquery
  git status
  • 测试jQuery能否能用
vim home.html
==>



    
    
    
    网易云音乐


    
--- :wq --- http-server -c-1 //模拟线上预览 (如果没有http-server 请安装 npm install http-server -g) http://localhost:8080/home.html //访问网页
  • http-server安装与介绍
    http-server 超轻量级web服务器
  • 上传到本地库
  git add .
  git commit -v ==> init home.html
  git status

补充:真正做开发时

  • 使用npm
  • 使用git
  • 使用http协议预览页面
  • 用gitignore 把node_modules 排除

  • 简化项目多余代码
  vi .gitignore  ==> /node_modules
  //把node_modules根目录隐藏,不上传到git仓库里
  //因为node_modules要安装很多需要的库,一个项目下来会特别大
  • 上传到本地库(别嫌麻烦,做好备份)
  git status 
  git add .gitignore
  git commit -v  ==> add ignore
  git status 
  • 上传到GitHub
  在GitHub新建空项目
  ...or push an existing repository from the command line
  代码抄写到git中
  //上传
  • 配置在线GitHub预览地址
    • Settings ↓↓↓
    • GitHub Pages ↓↓↓
    • Source ↓↓↓
    • master branch ---save
  • 预览
    预览页面会提示没有jQuery
    做到这一步的时候,因为我把node_modules上传到GitHub了。。
    删除了GitHub和本地的node_modules。
    所以需要重新安装一次jQuery
  npm i 
  ll node_modules //检查是否成功
  git add node_modules/jquery/dist/jquery.min.js
  会提示:
  // The following paths are ignored by one of your .gitignore files:
  // node_modules/jquery/dist/jquery.min.js
  // Use -f if you really want to add them.
  意思是:这个路径被你的gitignore给忽略了。如果你真的想添加他,使用 -f
  ok,everybody...
  git add node_modules/jquery/dist/jquery.min.js -f
  git commit -v   //add jquery
  • 编写首页
    html
  • 编写首页CSS
    使用动态REM
    

我的博客:动态REM是什么,如何使用

  • 代码过程中遇到的问题

    • inline-block BUG: SVG在div中,底部有点空白,给svg加vertical-align: top; 可以解决空隙。
    • 边框宽度0.5px:width: 200%; height: 200%;transform: scale(.5);
    • 内容自动收缩

      方法一:li中加div,给div设置display:inline-block;vertical-align: top;
      方法二(推荐):给li设置display: flex; justify-content: center; align-items: center;
    • 文本多行省略
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 3;
      overflow: hidden;
      文章:CSS实现单行、多行文本溢出显示省略号
    • display:flex: 设置flex里面的div,不会出现边距合并。
    • calc()实现33.3333%布局
      calc-CSS| MDN
      实现一个网易云音乐_第3张图片
      ⅓ - 2px,三排减6px,把6px分在中间两个空隙。
    • GitHub上的node_modules中的JQ没有响应。
      cp node_modules/jquery/dist/jquery.min.js ./ //把jquery移动到当前目录下
      mkdir vendors //创建文件夹
      mv jquery.min.js vendors/ //把jQuery 移动到文件下
      git add . git status git commit -v ==> move jquery git push //上传
    • 背景图自动填满 background-size: cover;
      background-size- CSS | MDN 文章
      实现一个网易云音乐_第4张图片
    • 边距合并:
      方法一(不推荐):overflow:hidden。触发BFC,解决边距合并。
      方法二:使用伪类,::before ==> content:""; display:table。
      方法二升级版:添加公共:
      .no-collapse::before{ content: ""; display: table; }
      .no-collapse::after{ content: ""; display: table; }
  • 七牛云(存储数据,生成在线URL)
    把歌曲和图片等下载到本地,上传到七牛云生成在线URL。

    • 存储文件
      管理控制台 --> 对象存储 --> 内容管理 --> 上传文件 --> 复制外链
  • leanClound实现在线获取数据
    leanClound网站

    • 创建应用 ==> 创建class(设置限制写入) ==> 创建Playlist和Song
      写入数据时,可以界面写入,也可以使用代码。

    • 使用代码 ==> 查看文档。
      帮助 --> 文档 --> 数据存储开发指南·javascript --> SDK安装 -->
      $ npm install leancloud-storage --save
      安装在 node_modules/leancloud-storage/dist文件下 ll+该路径查看是否成功
      cp node_modules/leancloud-storage/dist/av-min.js vendors //拷贝
      ll vendors // 验证文件是否存在
      添加到home.html中

    • 初始化
      var APP_ID = '6VgSKgCVd6rGXk9NI4hqQfO0-gzGzoHsz';
      var APP_KEY = 'Bs6J1KXLot6ifnFwYqePHdDo';
      AV.init({
      appId: APP_ID,
      appKey: APP_KEY
      });

    • 验证
      ping {{v2Domain}}
      然后在项目中编写如下测试代码:

      var TestObject = AV.Object.extend('TestObject');
      // 选择表名
      var testObject = new TestObject();
      // 生成一条数据
      testObject.save({
        words: 'Hello World!'
        //数据里面的内容
      }).then(function(object) {
        alert('LeanCloud Rocks!');
      })
      

      运行网页,如果成功,弹出"LeanCloud Rocks!"。


      实现一个网易云音乐_第5张图片
    • 例子:存一首歌

      var SongObject = AV.Object.extend('Song');
      var songObject = new SongObject();
      songObject.save({
        name: '像我这样的人',
        singer: '毛不易',
        url: 'http://oxklvemx3.bkt.clouddn.com/%E5%83%8F%E6%88%91%E8%BF%99%E6%A0%B7%E7%9A%84%E4%BA%BA.mp3'
      }).then(function(object) {
        alert('保存成功');
      })
      

      运行网页,如果成功,弹出"保存成功"。

    • 批量上传

      看文档 --> 数据存储开发指南·JavaScript --> 对象 --> 批量操作
      var SongObject = AV.Object.extend('Song');
      var songObject = new SongObject();
      songObject.set('name','1')
      songObject.set('singer','1')
      var songObject2 = new SongObject()
      songObject2.set('name','2')
      let songs = [songObject,songObject2]
      AV.Object.saveAll(songs)
      
    • 查询数据

      看文档 --> 数据存储开发指南·JavaScript --> 查询
      
      创建查询实例-->
      var query = new AV.Query('Todo');
      query.find().then(function (results) {
          console.log(results)
          //测试能否查询到
      }, function (error) {
      });
      在console.log输出所有歌曲信息,则查询成功-->
      
    • 使用数据

      最新音乐部分使用数据获取
      let $newList = $('ol#newList')
      // 创建查询
      var query = new AV.Query('Song');
      // query.startsWith('contain', 'true');
      query.find().then(function (results) {
          for( var i = 0;i
                   

      ${song.name} ${song.reMark}

      ${song.singer} - ${song.album}

    • ` $newList.append(li) } }, function (error) { });
    • 添加加载动画
      仅CSS实现的加载动画 – Loader.css

      npm i --save loaders.css  //安装
      cp node_modules/loaders.css/loaders.min.css vendors  //拷贝
      vim home.html --> 添加引用
      
      选择一个喜欢的样式
      .ball-grid-pulse > div {   //假设加载动画为ball-grid-pulse
         background: orange;    // 添加颜色
      }
      $('#songs-loading').remove()  //获取到数据后移除
      
    • 条件查询

      文档 --> 数据存储开发指南·JavaScript --> 查询 --> SQL查询
      var cql = 'select * from Todo where [列名] = [查询值]';
      AV.Query.doCloudQuery(cql).then(function (data) {
          // results 即为查询结果,它是一个 AV.Object 数组
          var results = data.results;
      }, function (error) {
      });
      
  • 搜索页面

        文档 --> 数据存储开发指南·JavaScript --> 查询 --> 字符串查询
        $('input#search').on('input',function(e){
              let $input = $(e.currentTarget)  // 当前点击的input
              let value = $input.val()   //input的值
              var query = new AV.Query('Song');   //选择表名
              query.contains('name',value);    //查询包含输入值的歌曲名
              query.find().then(function(result){
                  console.log(result)    //输出符合条件的信息
              })
          })
          ---------------------------搜索歌曲(替换以上代码)
          var $searchResult = $('#searchResult')  //显示搜索结果的div
          $('input#search').on('input',function(e){
              let $input = $(e.currentTarget)
              let value = $input.val().trim()    //trim()去掉字符串前后的空格
              if(value ==""){return $searchResult.empty()}
              //空的清除显示结果
    
              使用or组合查询,搜索歌手和歌曲名包含字符串的数据
              var query1 = new AV.Query('Song');
              var query2 = new AV.Query('Song');
              query1.contains('name',value);
              query2.contains('singer',value);
              var queryAll = AV.Query.or(query1, query2);
    
              query.find().then(function(results){
                  $searchResult.empty()
                  if(results.length === 0){
                      $searchResult.html('没有结果')
                  }else{
                      for( var i = 0; i
                              
                                  ${song.name} - ${song.singer}
                                  //注意a链接格式。
                                  //歌名和歌手在attributes中,id在results中
                          
  • ` $searchResult.append(li) } } }) })
    • 搜索使用函数节流-解决请求过多
      异步的特点,发出去的请求,不一定按顺序相应。所以输入时给一个等待时间,等全部打完之后,再进行搜索。比如设置300毫秒,在300毫秒内输入,就不进行搜索,等到有300毫秒的停顿,就进行搜索。

      设置闹钟
       var timer = null;
       <--- 当在input输入的时候
       if(timer){   //如果有定时器,清除定时器
         window.clearTimeout(timer)  
       }   //没有定时器,设置一个定时器,300毫秒执行
       timer = setTimeout(function(){
         console.log('结束输入')  //测试使用,可注释
         // 在这输入以上搜索代码
         timer = null
       },300)   //一般数值在300~500毫秒
      
  • 播放页面

    • 转动的光盘

      使用关键帧
      @keyframes spin{
        0%{
            transform: rotate(0deg)
        }
        100%{
            transform: rotate(360deg)
        }
      }
      section.disk > .circle.playing{
          animation: spin 10s linear infinite;  // 线性 循环
      }
      section.disk > .circle.playing.pause{
          animation-play-state:paused;   暂停动画
      }
      

      W3C:动画 CSS3 animation 属性
      W3C:转动 CSS3 transform 属性
      CSS3 动画暂停 animation-play-state 属性

    • 垂直居中专辑

      //知道了宽高 160px
      position: absolute;
      top: 50%;
      left: 50%;
      margin-top: -80px;
      margin-left: -80px;
      
    • 虚化图片,并变暗

      filter: blur(100px) brightness(.2);
      
    • querystring 获取当前url的id值
      搜索 querystring
      JS获取URL中参数值(QueryString)的4种方法分享

      function GetQueryString(name) {  
          var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");  
          var r = window.location.search.substr(1).match(reg);  
          //获取url中"?"符后的字符串并正则匹配
          var context = "";  
          if (r != null)  
              context = r[2];  
          reg = null;  
          r = null;  
          return context == null || context == "" || context == "undefined" ? "" : context;  
      }
      var id = GetQueryString("id");
      
    • 每一次使用leancloud都需要初始化,所以把初始化新建个js,用的时候就引用

      mkdir scripts  
      touch av.js
      
      each ===>
      var APP_ID = '6VgSKgCVd6rGXk9NI4hqQfO0-gzGzoHsz';
      var APP_KEY = 'Bs6J1KXLot6ifnFwYqePHdDo';
      AV.init({
      appId: APP_ID,
      appKey: APP_KEY
      });
      
    • 通过id获取歌曲信息

      文档 --> 数据存储开发指南·JavaScript --> 对象 
      --> 获取对象 --> 获取objectId 
      var query = new AV.Query('Song');
      query.get(id).then(function (song) {
          console.log(song)
      }
      
    • 拷贝歌词,上传到leancloud

    • 通过正则获取当前歌词

      query.get(id).then(function (song) { // 选择表明,并搜索id
          let {url,lyric} = song.attributes      // 获取歌曲url和歌词
          // ES6语法,等同 let url = song.attributes.url
          let video = document.createElement('video')    //创建video
          video.src = url;        // 歌曲url
          video.play()          // 播放歌曲
          let array = []        
          var parts = lyric.split('\n')    //把歌词字符串分割成字符串数组
          parts.forEach(function(string,index){   //遍历数组
              let xxx = string.split(']')      //以]分割成字符串数组
              xxx[0] = xxx[0].substring(1)    //删除第一个字符"["
              // xxx[0] 是歌词 ; xxx[1] 是索引
              //把时间转换成秒
              let regex = /(\d+):([\d.]+)/   //正则获取时间
              let matches = xxx[0].match(regex)    
              let minute = +matches[1]
              let seconds = +matches[2]
      
              array.push({
                  time: minute*60+seconds,
                  lyric: xxx[1]
              })
          })
          // console.log(array)
          setInterval(function(){
              // console.log(video.currentTime)
              let current = video.currentTime
              for(let i = 0;i current){
                      console.log(array[i].lyric)
                      break;
                  }
              }
          },500)
      })
      
    • 把歌词添加到页面上

      ---------------------------- let $lyric = $('.lyric') array.map(function(object){ let $p = $('

      ') $p.attr('data-time',object.time).text(object.lyric) $p.appendTo($lyric.children('.lines')) })

    • 页面播放原理

      
      // controls 会在浏览器显示控件
      
      ---  使用js向页面添加一个audio 并且把播放地址赋给url
       let audio = document.createElement('audio')
       audio.src = "//oxklvemx3.bkt.clouddn.com/xxx.mp3"
       audio.play()  //播放
      

      在线参考代码

    • 实现歌词滚动

      setInterval(function(){
      let seconds = video.currentTime
      // 获取音乐播放秒数
      let $lines = $('.lines > p')
      // 获取所有歌词标签
      let $whichLine
      for( let i = 0;i < $lines.length; i++){
          let currentLineTime = $lines.eq(i).attr('data-time')
          let nextLineTime = $lines.eq(i+1).attr('data-time')
          // let bug = $lines.eq(i+1).length !== 0   最后一行bug ==  $lines[i+1] !== undefined
          if( $lines[i+1] !== undefined && currentLineTime < seconds &&  nextLineTime > seconds ){
              $whichLine = $lines.eq(i)
              break;
          }
      }
      if($whichLine){
          $whichLine.addClass('active').prev().removeClass('active')
          let top = $whichLine.offset().top
          let linesTop = $('.lines').offset().top
          let delta = top - linesTop - $('.lyric').height()/3
          // 当前播放歌词距离顶部距离 -歌词容器距离顶部距离 - 一行歌词距离
          $('.lines').css(`transform`,`translateY(-${delta}px)`)
      }
      },500)

你可能感兴趣的:(实现一个网易云音乐)