我比较喜欢听音乐,特别是周末的时候,电脑开着百度随心听fm,随机播放歌曲,躺在床上享受。但碰到了一个烦人的事情,想切掉不喜欢的曲子,还得起床去操作电脑换歌。于是思考能不能用手机控制电脑切换歌曲,经过一段事件的思考,绝对采用html5+socket.io来实现这个功能。首先我把该功能的实现拆分为以下几个步骤:
1.移动端前端页面+脚本逻辑实现
2.PC端前端页面+脚本逻辑实现
3.后台逻辑实现
4.加入socket.io实现长连接
5.实现移动端控制PC端逻辑
1、移动端页面脚本的实现
html页面编写
仿造微信摇一摇的页面,实现一个类似的界面,如下所示:
当我们摇手机的时候,会做一个动画,中间的图案一分为二,上半部向上运动然后回来,下半部亦同理,如下所示:
移动端界面
HTML代码(shake.html):
样式表(shake.css):
脚本逻辑
接下来是移动端JS脚本逻辑的实现,摇一摇的实现需借助html5新增的devicemotion事件,获取设备在位置和方向上的改变速度的相关信息,该事件的基本使用如下:
devicemotion事件对象中有一个accelerationIncludingGravity属性,该属性包括:一个包含x、y 和z 属性的对象,在考虑z 轴自然重力加速度的情况下,告诉你在每个方向上的加速度。该API的具体使用大家可以参考网上的资料,非常多,这里就不重复了。
摇一摇的具体逻辑如下:
lastX = current.x;
lastY = current.y;
lastZ = current.z;
}
由于摇一摇需要播放摇一摇的声音以及切换歌曲成功后的声音,但由于手机大部分是禁止音频的自动播放,必须需要用户真实点击才能播放音频。这里没有彻底的解决办法,只是换了一个思路,利用用户随时触摸屏幕的习惯,对document进行touchstart事件监听。当用户触摸到屏幕时,先播放一个1S的无声音频,接着将touchstart事件移除,然后摇一摇的时候切换声音源,播放摇一摇的声音,这样便可以达到类似的目的。代码如下所示:
2、PC端前端页面脚本逻辑实现
html文档
PC端界面也是仿的网上的一个html5音乐播放器的界面,效果如下所示:
HTML(shake_pc.html)布局代码如下:
css样式
样式布局非常的简单,没什么好讲的。CSS样式代码(shake_pc.css)如下:
<div class="jb51code">
<pre class="brush: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.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,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,.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 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的效果,代码如下所示:
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服务器,接着监听事件即可,如下所示:
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播放的歌曲。
这个功能主要是我自己使用,可能有些细节没有进行处理,大家可以在该基础上进行改造,还可以做一些多屏互动的效果。
原文链接:https://www.f2er.com/js/42545.html