国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

利用HTML5+Socket.io實現搖一搖控制PC端歌曲切換

2019-11-19 17:57:46
字體:
來源:轉載
供稿:網友

我比較喜歡聽音樂,特別是周末的時候,電腦開著百度隨心聽fm,隨機播放歌曲,躺在床上享受。但碰到了一個煩人的事情,想切掉不喜歡的曲子,還得起床去操作電腦換歌。于是思考能不能用手機控制電腦切換歌曲,經過一段事件的思考,絕對采用html5+socket.io來實現這個功能。首先我把該功能的實現拆分為以下幾個步驟:

1.移動端前端頁面+腳本邏輯實現

2.PC端前端頁面+腳本邏輯實現

3.后臺邏輯實現

4.加入socket.io實現長連接

5.實現移動端控制PC端邏輯

1、移動端頁面腳本的實現

html頁面編寫

仿造微信搖一搖的頁面,實現一個類似的界面,如下所示:

當我們搖手機的時候,會做一個動畫,中間的圖案一分為二,上半部向上運動然后回來,下半部亦同理,如下所示:

移動端界面

html代碼(shake.html):

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no">  <title>搖一搖切歌</title>  <link rel="stylesheet" href="shake.css"></head><body>  <div class="wrap" id="wrap">    <div class="inner"></div>    <div class="above-hand hand" id="up"></div>    <div class="below-hand hand" id="bt"></div>  </div>  <div class="tip" id="tip">      </div>  <div style="display: none;">    <audio id="shaking" src="new_silent.mp3"></audio>    <audio id="found" src="new_silent.mp3"></audio>  </div>  <script type="text/javascript" src="socket.io.js"></script>  <script src="shake.js"></script></body></html>

樣式表(shake.css):

html,body{      width:100%;	  height:100%;	  background-color: #000;	  margin:0; 	  overflow: hidden;	 }.wrap{    position: absolute;	left:50%; top:50%;	width:132px; 	height: 132px;	-webkit-transform: translate(-50%,-50%);	transform: translate(-50%,-50%);    }.hand{     position: absolute;     left:0;     width:100%;     height: 50%;    background: url(shake.png) no-repeat #000;    background-size: 132px 132px;   }.above-hand{       top:0;	   background-position: 0 0;	  }.below-hand{        bottom:0; 	   background-position: 0 -66px;	  }.inner{    position:absolute;	top:50%; 	left:50%;	width: 50px;	height: 90px;	background: url(inner.png) no-repeat 0 0;	background-size: 50px 90px; 	-webkit-transform: translate(-50%,-50%);	transform: translate(-50%,-50%);   }.above-hand:after,.below-hand:before{                     display: none;				    content:'';				    position:absolute;				    left:-100vw;				    width:200vw;				    height: 2px;				    background-color: #BABDC1; 				  }.above-hand:after{ bottom:0; }.below-hand:before{ top:0; }.wrap.active .above-hand{               -webkit-animation: up 1.5s ease;			  animation: up 1s ease;			}.wrap.active .below-hand{             -webkit-animation: down 1.5s ease;			 animation: down 1s ease; 			}.wrap.active .above-hand:after,.wrap.active .below-hand:before{ display: block; }.tip{     position: absolute;	 bottom: 30px; left: 10px; 	 color: #fff; font-family: '楷體'; 	 text-align: center; right: 10px;	 height: 32px; line-height: 32px; 	 background-color: rgba(255,255,255,.4);	 border-radius: 3px;    } .tip.active{        -webkit-animation: jump 1.5s linear; 	   animation: jump 1s linear; 	  }

腳本邏輯

接下來是移動端JS腳本邏輯的實現,搖一搖的實現需借助html5新增的devicemotion事件,獲取設備在位置和方向上的改變速度的相關信息,該事件的基本使用如下:

if(window.DeviceMotionEvent){  window.addEventListener('devicemotion',handler,!1);}else{  alert('你的瀏覽器不支持搖一搖功能.');}

devicemotion事件對象中有一個accelerationIncludingGravity屬性,該屬性包括:一個包含x、y 和z 屬性的對象,在考慮z 軸自然重力加速度的情況下,告訴你在每個方向上的加速度。該API的具體使用大家可以參考網上的資料,非常多,這里就不重復了。

 搖一搖的具體邏輯如下:

function handler(e){  var current = e.accelerationIncludingGravity;  var currentTime;  var timeDifference;  var deltaX = 0;  var deltaY = 0;  var deltaZ = 0;  //記錄上一次設備在x,y,z方向上的加速度  if ((lastX === null) && (lastY === null) && (lastZ === null)) {    lastX = current.x;    lastY = current.y;    lastZ = current.z;    return;  }  //得到兩次移動各個方向上的加速度絕對差距  deltaX = Math.abs(lastX - current.x);  deltaY = Math.abs(lastY - current.y);  deltaZ = Math.abs(lastZ - current.z);  //當差距大于設定的閥值并且時間間隔大于指定閥值時,觸發搖一搖邏輯  if (((deltaX > threshold) && (deltaY > threshold)) || ((deltaX > threshold) && (deltaZ > threshold)) || ((deltaY > threshold) && (deltaZ > threshold))) {    currentTime = new Date();    timeDifference = currentTime.getTime() - lastTime.getTime();    if (timeDifference > timeout) {      dealShake();      lastTime = new Date();    }  }  lastX = current.x;  lastY = current.y;  lastZ = current.z;}

由于搖一搖需要播放搖一搖的聲音以及切換歌曲成功后的聲音,但由于手機大部分是禁止音頻的自動播放,必須需要用戶真實點擊才能播放音頻。這里沒有徹底的解決辦法,只是換了一個思路,利用用戶隨時觸摸屏幕的習慣,對document進行touchstart事件監聽。當用戶觸摸到屏幕時,先播放一個1S的無聲音頻,接著將touchstart事件移除,然后搖一搖的時候切換聲音源,播放搖一搖的聲音,這樣便可以達到類似的目的。代碼如下所示:

document.addEventListener('touchstart',autoplay,!1);function autoplay(){  shaking.play();  found.play();  document.removeEventListener('touchstart',autoplay);}

2、PC端前端頁面腳本邏輯實現

html文檔

PC端界面也是仿的網上的一個html5音樂播放器的界面,效果如下所示:

HTML(shake_pc.html)布局代碼如下:

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>隨心聽</title>  <meta name="referrer" content="never">  <link rel="stylesheet" href="reset2.0.css">  <link rel="stylesheet" href="shake_pc.css"></head><body>  <!-- 控制背景圖效果 -->  <div class="bg" id="bg">  </div>  <div class="music-player">     <!-- 歌曲信息 -->    <div class="info">      <div class="song-name" id="songName"></div>      <div class="author" id="author">By <span></span></div>       <!-- 播放進度 -->      <div class="progress" id="progress"></div>    </div>     <!-- 歌曲控制 -->    <div class="controls">      <div class="time" id="time">00:00</div>      <div class="play-controls">        <a href="javascript:;" class="prev btn" id="prev">        </a><a href="javascript:;" class="play btn" id="play">        </a><a href="javascript:;" class="next btn" id="next"></a>      </div>      <div class="volume-bar">        <a href="javascript:;" class="vol-muted" id="muted">        </a><a href="javascript:;" class="vol-slider" id="volSilder">          <span class="vol-slider-inner" id="volInner"></span>        </a><a href="javascript:;" class="vol-max" id="volMax"></a>      </div>    </div>     <!-- 歌曲播放 -->    <audio id="audio" controls style="display: none;"></audio>  </div>  <script type="text/javascript" src="socket.io.js"></script>  <script type="text/javascript" src="shake_pc.js"></script></body></html>

css樣式

樣式布局非常的簡單,沒什么好講的。CSS樣式代碼(shake_pc.css)如下:

body{   font-family: 'Open Sans', sans-serif;    overflow: hidden;   }.bg{    position: absolute;   left:0; right: 0;top:0;    bottom: 0;margin:-30px;   filter: blur(30px);    -webkit-filter: blur(30px);   background: url(./imgaes/bg.jpg) no-repeat;    background-size: cover;  }.music-player{         position: relative;	    width: 350px;	    height: 290px;	    margin: 150px auto; 	    box-shadow: 0 0 60px rgba(0, 0, 0, 0.8);	    border-radius: 7px;	    background: #222;	    overflow: hidden;	    z-index: 0;	   }.info{    position: relative;    width: 100%;    height: 80px;     padding-top: 20px;    color:#585858;    text-align: center;    }.info .song-name{           height: 30px; 		  font-size: 30px;		  font-weight: 300;		 }.info .author{         margin-top: 14px;	    font-size: 14px;	   }.progress{      position: absolute; 	  left:0; bottom:0;	  width: 0; 	  height: 3px; 	  background-color: #ed553b;	 }.controls{      height: 190px; 	  background-color:rgba(152, 46, 75, 0.6);	  text-align: center;	 }.controls .time{          font-size:48px; 		 height: 84px; 		 line-height: 84px; 		 color:rgba(225, 225, 225, 0.4); 		}.play-controls .btn{           display: inline-block;		   width:95px; 		   height: 40px;		   vertical-align: top;		  }.play-controls .btn.prev{ background:url(./imgaes/prev.png) no-repeat center center; }.play-controls .btn.play{ background:url(./imgaes/play.png) no-repeat center center; }.play-controls .btn.next{ background:url(./imgaes/next.png) no-repeat center center; }.volume-bar{        position: relative; 	   width:250px;	   height: 2px; 	   margin: 30px auto 0;	  }.volume-bar .vol-muted{             position:absolute; 			 left:0;			 top:-6px; 			 width: 10px;			 height:13px;			 background:url(./imgaes/muted.png) no-repeat center center; 		   }.volume-bar .vol-slider{              position: absolute; 			 left:14px;			 right:28px;			 top:0; height:100%; 			 background-color:rgba(255,255,255,.3); 		   }.volume-bar .vol-slider-inner{                display: block;			    width:50%; 			    height: 100%;			    background-color:#ed553b; 			   }.volume-bar .vol-max{           position:absolute; 		   right:0;		   top:-8.5px;		   width: 22px;		   height: 18px;		   background: url(./imgaes/max.png) no-repeat center center;		   }

腳本邏輯

文檔加載完成后,隨機獲取一首音樂,然后播放。點擊上一曲或下一曲都是隨機切換歌曲,以及可以對音量進行控制,有興趣的朋友還可以自行實現歌詞的同步播放。有關html5媒體原生API,大家可以參考HTML5的Video標簽的屬性,方法和事件匯總
 部分代碼如下:

var mediaEvts = ['loadedmetadata','ended','timeupdate','error'];//隨機獲取一首音樂function getSong(){  return new Promise(function(resolve,reject){    var xhr = new XMLHttpRequest();    xhr.onreadystatechange = function() {      if (xhr.readyState === 4) {        if (xhr.status === 200) {          resolve(xhr.responseText);        }else{          reject('發生錯誤');        }      }    };    xhr.open('get', 'http://api.jirengu.com/fm/getSong.php?channel=1', !0);    xhr.send();  });}function dealSong(responseText){  var songObj = JSON.parse(responseText),    song = songObj.song[0];  updateUI(song);  setMedia(song);  return song;}function setMedia(song){  var songSrc = song.url,    lrc = song.lrc;  player.src = songSrc;  player.volume = 0.5;  player.play();}function updateUI(song){  var name = song.title,    artist = song.artist,    img = song.picture;  songName.innerText = name;  author.querySelector('span').innerText = artist;  bg.style.backgroundImage = 'url('+img+')';}//初始化audio元素事件監聽function initMediaEvents(player){  mediaEvts.forEach(function(evt,idx,arr){    var cb = evt+'CB';    player.addEventListener(evt,window[cb],!1);  });}

3、后臺實現

使用express+socket.io實現長連接,socket.io可以利用npm進行安裝。根據UA實現PC+移動端渲染不同的頁面,將移動端的發送的命令廣播給PC端,然后達到移動端控制PC的效果,代碼如下所示:

const http = require('http');var express = require('express');var app = express();var server = require('http').Server(app);var io = require('socket.io')(server);app.use(express.static('./'));app.get('/',(req,res)=>{  var userAgent = req.headers['user-agent'].toLowerCase();  if(/(android|iphone|mobile)/.test(userAgent)){    res.sendFile(__dirname+'/shake_m.html');  }else{    res.sendFile(__dirname+'/shake_pc.html');  }});io.on('connection',function(socket){  var usrname = '',    sendData = {};  console.log('a client connect...'+socket.id);  socket.on('disconnect',function(){    console.log(`設備${socket.id}斷開連接.`);  });  socket.on('message',function(data){    var cmd = data.cmd;    //next命令是由移動端發送,OK命令是由PC切歌成功后發送的命令    if(cmd == 'next'){      socket.broadcast.emit('next');    }else if(cmd == 'ok'){      socket.broadcast.emit('ok',data.data);    }  });});server.listen(3000,function(){  console.log('start listening on 3000 port...');});

4、移動端和PC端加上socket.io

首先在頁面中引入socket.io.js,然后連接socket服務器,接著監聽事件即可,如下所示:

//移動端socket邏輯socket.on('connect',function(){  console.log('websocket連接已建立...');});socket.on('ok',function(data){  if(found.src!=host+'found.mp3'){    found.src = 'found.mp3';  }  found.play();  tip.innerText = '正在欣賞:'+data.artist+'--'+data.title;  tip.classList.remove('active');  tip.offsetWidth = tip.offsetWidth;  tip.classList.add('active');});function dealShake(){  if(isShaking) return;  isShaking = !0;  if(shaking.src!=host+'shaking.mp3'){    shaking.src = 'shaking.mp3';  }  shaking.play();  wrap.classList.add('active');  setTimeout(function(){    socket.emit('message',{cmd:'next',data:null});  },1000);  }//PC端socket邏輯function initIOEvts(){  socket.on('connect',function(){    console.log('websocket連接已建立...');  });  socket.on('next',function(data){    getSong().then(function(val){      var song = dealSong(val);      socket.emit('message',{cmd:'ok',data:song});    },function(err){      console.log(err);    });  });}

當用戶搖動設備觸發搖一搖時,發送一個next命令的消息給服務端,然后服務端將該消息轉發給PC端,PC端接收到該消息后,執行歌曲切換操作,并反饋一個ok命令消息并攜帶歌曲消息給服務端,服務端再將該消息轉發回移動端,移動端播放切歌成功的聲音并顯示當前PC播放的歌曲。

這個功能主要是我自己使用,可能有些細節沒有進行處理,大家可以在該基礎上進行改造,還可以做一些多屏互動的效果。

demo下載:http://xiazai.VeVB.COm/201701/yuanma/shake-music_jb51.rar

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 同心县| 博罗县| 寿阳县| 潮安县| 乐清市| 广水市| 法库县| 陕西省| 会昌县| 定陶县| 澄江县| 永胜县| 郁南县| 乡宁县| 星座| 南部县| 沂南县| 德阳市| 双峰县| 静乐县| 灵宝市| 景谷| 西峡县| 监利县| 仪陇县| 信丰县| 通州市| 无棣县| 尚志市| 修文县| 卢龙县| 同仁县| 武强县| 连云港市| 柳州市| 卢氏县| 习水县| 五原县| 常熟市| 珲春市| 沂源县|