假期哪也没去,宅在寝室实现了两个播放器实例,基于HTML5的,一个是播放单一歌曲的,为博客文章内嵌音乐准备的;另一个是列表播放器,完全就是要拿来替代桌面播放器的(虽然还远没有达到目标)。单曲版播放器的Demo已经放出,地址在:http://mynook.info/try/yplayer/,另一个播放器的Demo我会尽快放出。现在先贴完整版播放器的代码。写得比较粗糙,高手见笑了。因为没有地方可以抓取ogg格式的音乐,所以这个实例只支持Chrome和Safari(只在Chrome测试过。)。(音乐从点点网抓取,可能需要先在浏览器上登录点点网才能获取读权限。)

以下是页面。

<!doctype html>
<html>
 <head>
    <meta charset="utf-8" />
    <title>YPlayer Full Version Demo</title>
    <link rel="stylesheet" href="yplayer.css" />
    <script type="text/javascript" src="playlist.js"></script>
    <script type="text/javascript" src="yplayer.js"></script>
 </head>

 <body>
    <div id="container">
      <div id="YPlayer">
        <audio controls id="YPlayer audio">
        </audio>
        <a href="javascript:void(0)" id="playBtn" title="播放"><span id="playIcon"></span></a>
        <a href="javascript:void(0)" id="volumeBtn" title="静音"><span id="volumeIcon"></span></a>
        <a href="javascript:void(0)" id="loopBtn" title="当前不循环"><span id="loopIcon"></span></a>
        <a href="javascript:void(0)" id="helpBtn" title="关于"><span id="helpIcon"></span></a>
        <div id="progressBar">
          <span id="bufferProgress">
            <span id="audioProgress"></span>
          </span>
        </div>
        <input type="range" id="volumeBar" min="0" max="1" step="0.01" />
      </div>
      <div id="playList">
        <ol>
          <li><a href="javascript:void(0)">初音未来 - 比以往更爱哭的天空</a></li>
        </ol>
      </div>
    </div>
    <script type="text/javascript">
      document.onreadystatechange = function(){
        if(document.readyState == 'complete'){
           var list = yplayer.loadList(playList);
           var player = new yplayer.ui();
        }
      }
    </script>
  </body>
</html>

下面是播放器的js代码,引用在 yplayer.js 文件中。

/**
 * YPlayer HTML5 player
 * 
 * @author Joker Qyou
 * @copyright Copyright (c) 2012 Joker Qyou <a href="(http://mynook.info/)" target="_blank">(http://mynook.info/)</a>
 * @License  GNU General Public License 2.0
 * @Version $id$
 */


if(typeof yplayer == 'undefined'){
  yplayer = function(){}
}


// This controls the main functions of the player, include shortcuts.
yplayer.ui = function(){

  // Buttons and progress bar vars.
  var yplayerObj = document.getElementById('YPlayer audio');
  var yplayerPlayBtn = document.getElementById('playBtn');
  var yplayerVolBtn = document.getElementById('volumeBtn');
  var yplayerLoopBtn = document.getElementById('loopBtn');
  var yplayerHelpBtn = document.getElementById('helpBtn');
  var yplayerVol = document.getElementById('volumeBar');
  var yplayerPro = document.getElementById('audioProgress');
  var yplayerBufferPro = document.getElementById('bufferProgress');
  var yplayerProVal;
  var yplayerBufferProVal;
  var loopType = ['none','current','list'];
  var nowLoopType = 'none';

 // Icon vars.
  var yplayerPlayIcon = document.getElementById('playIcon');
  var yplayerVolumeIcon = document.getElementById('volumeIcon');
  var yplayerLoopIcon = document.getElementById('loopIcon');

  var listItems = document.getElementById('playList').getElementsByTagName('a');

  // Extend the show() method of Object.
  Object.prototype.show = function(){
    this.style.display = 'block';
    return this;
  }

 // Extend the hide() method of Object.
  Object.prototype.hide = function(){
    this.style.display = 'none';
    return this;
  }

 // Extend the click() method of Object.
 Object.prototype.click = function(){
    if (/msie/i.test(navigator.userAgent)){
      this.fireEvent('onclick');
    }else{
      var e = document.createEvent('MouseEvent');
      e.initEvent('click', false, false);
      this.dispatchEvent(e);
    }
 }

 // Extend the indexOf() method of Array.
  Array.prototype.indexOf = function(elem){
    for(var i = 0; i < this.length; i ++){
      if(elem == this[i]){
        return i;
      }
    }
    return 'Not In the Array.';
 }

 // Hide default controllers and the whole audio.
  yplayerObj.controls = false;
  yplayerObj.preload = 'auto';
  yplayerObj.hide();

  // Add 'play and pause' controllers.
  yplayerPlayBtn.addEventListener('click', function(){
    if(yplayerObj.paused || yplayerObj.ended){
      yplayerObj.play();
      yplayerPlayBtn.title = '暂停';
    }else{
      yplayerObj.pause();
      yplayerPlayBtn.title = '播放';
    }
 });

 // Add 'mute' controller.
 yplayerVolBtn.addEventListener('click', function(){
   yplayerObj.muted = !yplayerObj.muted;
   if(yplayerObj.muted){
     yplayerVolumeIcon.style.backgroundPosition = '0 -240px';
     yplayerVolBtn.title = '解除静音';
   }else{
     yplayerVolumeIcon.style.backgroundPosition = '0 -640px';
     yplayerVolBtn.title = '静音';
   }
 });

 // Show volume bar.
 yplayerVolBtn.addEventListener('mouseover', function(){
   yplayerVol.show();
  });

 // Hide volume bar.
 yplayerVol.addEventListener('mouseout', function(){
   yplayerVol.hide();
  });

 // Set volume via volume bar.
 yplayerVol.addEventListener('change', function(){
   yplayerObj.volume = yplayerVol.value;
 });

 // Update time to progress.
 yplayerObj.addEventListener('timeupdate', function(){
   (yplayerObj.currentTime > 0 && yplayerObj.currentTime < yplayerObj.duration) ? yplayerProVal = Math.floor((300 / yplayerObj.duration) * yplayerObj.currentTime) : yplayerProVal = 0;
    yplayerPro.style.width = yplayerProVal + 'px';
    var rangesLength = yplayerObj.buffered.length;
    var BufferProVal = yplayerObj.buffered.end(rangesLength - 1);
   yplayerBufferProVal = Math.floor((300 * BufferProVal) / yplayerObj.duration);
   yplayerBufferPro.style.width = yplayerBufferProVal + 'px';
  });

 yplayerObj.addEventListener('play', function(){
   yplayerPlayIcon.style.backgroundPosition = '0 -320px';
  });

 yplayerObj.addEventListener('pause', function(){
    yplayerPlayIcon.style.backgroundPosition = '0 -400px';
  });

 // Reset play button image when song ends.
  yplayerObj.addEventListener('ended', function(){
    yplayerPlayIcon.style.backgroundPosition = '0 -400px';
    yplayerPlayBtn.title = '播放';
    for(var i = 0; i < listItems.length; i ++){
     listItems[i].className ='';
   }
   yplayerBufferPro.style.width = 0 + 'px';
    if(nowLoopType == 'current'){
     yplayerObj.play();
    }else if((nowLoopType == 'list') && (_now < (_list.length - 1))){
     yplayer.loadSrc(_now + 1);
    }else if((nowLoopType == 'list') && (_now >= (_list.length - 1))){
      yplayer.loadSrc(0);
   }
 });

 // Loop controller.
 yplayerLoopBtn.addEventListener('click', function(){
    // yplayerObj.loop = !yplayerObj.loop;
    // if(yplayerObj.loop){
   //  yplayerLoopIcon.style.backgroundPosition = '0 -480px';
    // }else{
   //  yplayerLoopIcon.style.backgroundPosition = '0 -160px';
    // }
    var nowLoopIndex = loopType.indexOf(nowLoopType);
   if(nowLoopIndex < (loopType.length - 1)){
     nowLoopType = loopType[nowLoopIndex + 1];
   }else if(nowLoopIndex >= (loopType.length - 1)){
      nowLoopType = loopType[0];
    }
   if(nowLoopType == 'none'){
      yplayerLoopIcon.style.backgroundPosition = '0 -160px';
      yplayerLoopBtn.title = '当前不循环';
   }else if(nowLoopType == 'current'){
     yplayerLoopIcon.style.backgroundPosition = '0 -560px';
      yplayerLoopBtn.title = '当前单曲循环';
    }else if(nowLoopType == 'list'){
      yplayerLoopIcon.style.backgroundPosition = '0 -480px';
      yplayerLoopBtn.title = '当前列表循环';
    }
 });

 yplayerHelpBtn.addEventListener('click',function(){
   var yplayerAbout = '<!doctype html><html><head><title>About YPlayer</title></head><body><div style="text-align: center;margin-top: 3em;font-family: Geneva,Arial,sans-serif;"><div style="font-size: xx-large">YPlayer for Blog</div><div style="font-size: 1em;margin-bottom: 4em;"><div>Version 1.1 (April 3 2012)</div><div><a href="http://mynook.info/" target="_blank" style="color:#0099FF;text-decoration:none;">http://mynook.info/</a></div><div>If you like this script, please <a href="https://me.alipay.com/jokerqyou" target="_blank" style="color:#0099FF;text-decoration:none;">donate</a> to keep development active!</div></div><div>HTML5 Music Player</div></div></body></html>';
    var yplayerAboutWindow = window.open('about:blank','YPlayerAbout','resizable=no,width=400,height=300,toolbar=no,menubar=no,location=no,status=no');
   yplayerAboutWindow.document.write(yplayerAbout);
  });

 // Set shortcut keys.
 document.addEventListener('keydown', function(event){// The 'event' parameter is for Firefox.
   if(event.keyCode == 32){// Space -> play/pause.
     yplayerPlayBtn.click();
   }else if(event.keyCode == 38){// Up -> volume up.
     yplayerVol.show().focus();
      var oldvol = yplayerVol.value * 100;
      var newvol = (oldvol ++) / 100;
     yplayerVol.value = newvol;
    }else if(event.keyCode == 40){// Down -> volume down.
     yplayerVol.show().focus();
      var oldvol = yplayerVol.value * 100;
      var newvol = (oldvol --) / 100;
     yplayerVol.value = newvol;
    }else if(event.keyCode == 76){// L -> loop/unloop.
      yplayerLoopBtn.click();
   }else if(event.keyCode == 77){// M -> mute/unmute.
      yplayerVolBtn.click();
    }else if(event.keyCode == 65){// A -> help/about.
     yplayerHelpBtn.click();
   }else if(event.keyCode == 37){// Left -> Previous.
      if(_now > 0){
       yplayer.loadSrc(_now - 1);
      }else{
        yplayer.loadSrc(_list.length - 1);
      }
   }else if(event.keyCode == 39){// Right -> Next.
     if(_now < (_list.length - 1)){
        yplayer.loadSrc(_now + 1);
      }else{
        yplayer.loadSrc(0);
     }
   }
 });

 // Hide volume bar after setting volume.
  document.addEventListener('keyup', function(event){// The 'event' parameter is for Firefox.
   if(event.keyCode == 38 || 40){
      yplayerVol.hide();
    }
 });


}


// This is the function for loading playlist.
yplayer.loadList = function(list){
 if(!list){
    return 'List Empty.';
 }else{
    var listArea = document.getElementById('playList');
   var yplayerObj = document.getElementById('YPlayer audio');
    listArea.innerHTML = '';
    var olist = document.createElement('ol');
   for(var i = 0; i < list.length; i ++){
      var listItem = document.createElement('li');
      var listLink = document.createElement('a');
     listLink.innerHTML = list[i].singer + ' - ' + list[i].title;
      listLink.href = 'javascript:void(0)';
     listLink.setAttribute('data-num', i);
     listLink.setAttribute('onclick', 'yplayer.loadSrc(' + i + ');');
      listItem.appendChild(listLink);
     olist.appendChild(listItem);
    }
   listArea.appendChild(olist);
    yplayer.loadSrc(0);// Autoload the first item in the playlist.
    _list = list;// Sorry again for no better idea.
 }
}


// Sorry I have no better idea about this.
yplayer.loadSrc = function(i){
  var yplayerObj = document.getElementById('YPlayer audio');
  var listItems = document.getElementById('playList').getElementsByTagName('a');
  yplayerObj.src = playList[i].URL[0];
  for(var n = 0; n < listItems.length; n ++){
   listItems[n].className = '';
  }
 listItems[i].className = 'nowplaying';
  _now = i;
 yplayerObj.play();
}
</code>

以下是播放列表,引用于playlist.js文件中。

<code lang="javascript">
var playList = [
  {
   title: "比以往更爱哭的天空",
   singer: "初音未来",
   URL: [
      "http://a.libdd.com/farm1/81/13FFC6C54F043A66FF4B790558E1E351.mp3"
    ]
 },
  {
   title: "Mother",
    singer: "久石让",
    URL: [
      "http://a.libdd.com/farm1/207/D45D0FF4A88EBABEE99DE5C661387ACF.mp3"
   ]
 },
  {
   title: "When A Child Is Bron",
    singer: "圣菲利普童声合唱团",
    URL: [
      "http://a.libdd.com/farm1/86/48CA8DFD3E1FC5729E00FE2693CBD156.mp3"
    ]
 },
  {
   title: "夜的第七章",
   singer: "周杰伦",
    URL: [
      "http://a.libdd.com/farm1/60/4F84F444FD34BAEF721DF876D23A583C.mp3"
    ]
 },
  {
   title: "初めての恋が終わる時",
    singer: "初音未来",
   URL: [
      "http://a.libdd.com/farm1/215/1BA3C3ECA993F78B20EE12CB46101AD7.mp3"
   ]
 },
  {
   title: "Puzzle",
    singer: "初音未来",
   URL: [
      "http://a.libdd.com/farm1/24/0D205D62A39B5325FB80F4575637CE18.mp3"
    ]
 },
  {
   title: "Ura Omote Lovers",
    singer: "初音未来",
   URL: [
      "http://a.libdd.com/farm1/118/DA79841501F29C1CAEF4BFC5C70E7976.mp3"
   ]
 },
  {
   title: "Rolling Girl",
    singer: "初音未来",
   URL: [
      "http://a.libdd.com/farm1/162/9A11223FB9BAE7A45851B7E912645CA2.mp3"
   ]
 },
  {
   title: "星屑乌托邦",
   singer: "巡音流歌",
   URL: [
      "http://a.libdd.com/farm1/33/74504BE15676688A7B649F4A2E941E21.mp3"
    ]
 },
  {
   title: "色は匂へど散りぬるを",
    singer: "senya",
    URL: [
      "http://mu6.me/file/f4p403d2b4"
   ]
 }
]

以下是样式表。

html,body,input{
 outline: none;
}

#container{
  padding: 14px;
  border: 1px solid #bbb;
 width: auto;
  height: auto;
 display: inline-block;
  border-radius: 3px;
 -webkit-border-radius: 3px;
}

#YPlayer{
 padding: 0 6px 5px 1px;
 display: inline-block;
  border: 1px solid #bbb;
}

#playBtn,#playIcon,#volumeBtn,#volumeIcon,#loopBtn,#loopIcon,#helpBtn,#helpIcon{
  height: 30px;
 width: 30px;
  display: inline-block;
  padding: 0;
 margin: 0 0 0 2px;
}

#playIcon{
 background: url(./sprite.png) no-repeat;
  background-position: 0 -400px;
}

#volumeBtn{
  margin-left: 1px;
}

#volumeIcon{
  background: url(./sprite.png) no-repeat;
  background-position: 0 -640px;
  margin-left: 1px;
}

#loopIcon{
  background: url(./sprite.png) no-repeat;
  background-position: 0 -160px;
  margin-left: -1px;
}

#helpIcon{
 background: url(./sprite.png) no-repeat;
  background-position: 0 -80px;
 margin-left: -2px;
}

#volumeBar{
  -webkit-appearance: slider-horizontal;
  padding: 0e;
  display: none;
  width: 420px;
 margin: 4px auto 0 auto;
}

#progressBar{
  display: inline-block;
  width: 300px;
 margin: 8px 0 0 0;
  padding: 0;
 height: 30px;
 background: #d7d7d7;
  border: 1px solid #bbb;
 border-radius: 2px;
 -webkit-border-radius: 2px;
 -moz-border-radius: 2px;
}

#bufferProgress{
 display: inline-block;
  height: 30px;
 background-color: #CCE4FF;
  padding: 0;
 margin: 0;
  border-radius: 1px;
 -webkit-border-radius: 1px;
 opacity: 0.6;
 -moz-opacity: 0.6;
  filter:alpha(opacity=6);
}

#audioProgress{
  display: inline-block;
  border-radius: 1px;
 -webkit-border-radius: 1px;
 -moz-border-radius: 1px;
  background-color: #4389DC;
  height: 30px;
 padding: 0;
 margin: 0;
  opacity: 0.6;
 -moz-opacity: 0.6;
  filter:alpha(opacity=6);
}

#playList{
 border: 1px solid #bbb;
 padding: 0 10px;
  margin-top: 10px;
 width: 436px;
 min-height: 30px;
}

#playList ol{
 list-style: none;
 -webkit-padding-start: 0;
}

#playList ol li{
  border-bottom: 1px dashed #bbb;
 font-size: 16px;
  text-align: left;
 font-weight: bold;
  padding: 4px 0;
}

#playList ol li:first-child{
  border-top: 1px dashed #bbb;
}

#playList ol li:last-child{
  border-bottom: 1px dashed #bbb;
}

#playList ol li a{
  text-decoration: none;
  color: #666;
  padding: 4px 0;
}

#playList ol li a.nowplaying{
 color: #000;
  padding-left: 18px;
 background: url(./nowplaying.png) no-repeat;
  background-position: 0 8px;
}

从来没有贴过这么长的文章,原谅我吧。。。ORZ…