node-webkit-MusicBox 基于nwjs ,html5 ,制作的音乐盒子

article/2025/11/5 17:32:22

太长?单击目录直接去看最终效果,在最下边



文件下载地址:http://download.csdn.net/detail/u013934914/9180053

1.思路(简单设想)

index.html 实现 对页面的显示,并调用绑定ymusic.js中的方法
需要:绘出基本页面样式实现窗口的放大缩小关闭实现调用播放器对象,并实现对事件的监听,通过监听改变文字或样式等ymusic.js 实现对播放器的再次封装;(为了方便控制):
需要:重写html5的事件加入播放列表功能加入歌词功能(正在实现...)加入播放模式


2.index.html的实现

这里只是一部分概括的js代码,具体在https://github.com/ymma/node-webkit-MusicBox/blob/master/music/index.html

<script>var gui = require("nw.gui");mwin = gui.Window.get();$(function(){//这里绑定window的一些事件,比如关闭和缩小,可扩展var windBarEvent = function(){$('#win_btn_close').click(function(){});$('#win_btn_min').click(function(){});}windBarEvent();music();});//之所以不写成类的形式,因为数据不统一,抽象成类太麻烦,太杂function music(){//一些全局变量var musicList = [] ,  //播放列表的数据playListNow,    //正在播放的列表的索引media;          //播放器对象//一些dom节点var domPgNow = $('#pgNow'),domBody = $('.body'),     //主要是为了设置背景图片domUlCList = $('#ulCList') , //所有列表domUlMList = $('#ulMList'), //当前音乐播放列表...//包括播放,暂停,上一首,下一首等事件var barEvent = function(){},//创建播放器,并绑定修改样式的一些方法createMedia = function(){},//给音乐列表赋予数据loadListData = function(){},//加载播放列表的一些方法loadList = function(){var loadPlayHtml = function(num){  //加载第num个列表中的音乐列表,正在播放的列表的html},loadListHtml = function(){  //加载列表[比如默认列表,手机列表,xxx]}loadListHtml();loadPlayHtml(playListNow);  //加载第n个列表}//加载歌词的一些方法loadLrc = function(arr){}loadListData(); //1,加载列表数据createMedia();  //2,加载播放器对象barEvent();     //3,加载基本事件loadList();     //4,加载列表的HTML,并绑定事件}
</script>


3.ymusic.js

文件在这:https://github.com/ymma/node-webkit-MusicBox/blob/master/music/public/js/ymusic.js

var fs = require("fs");
var iconv = require('iconv-lite'); 
var Utils = {calcTime : function(time){var hour,minute,second,timer = '';hour = String(parseInt(time/3600,10));minute = String(parseInt((time % 3600) / 60 ,10));second = String(parseInt(time % 60, 10));if(hour != '0'){if(hour.length == 1) hour = '0' + hour;timer += (hour + ':');}if(minute.length == 1) minute = '0' + minute;timer += (minute + ':');if(second.length == 1) second = '0' + second;timer += second;return timer;},/*** 获取随机数,在min和max之间,且不能为not*/getRandom : function(notIndex ,min ,max){var temp=[];for(var i=min;i<=max;i++){ if(i != notIndex){ temp.push(i); } }return temp[parseInt(Math.random() * temp.length)];}
}function YMedia(arg){this.arg = arg;this.init();
}
YMedia.prototype = {/*** 基本配置*/config : {musicMode : ['单曲播放','单曲循环','顺序播放','循环播放','随机播放']},/*** 初始化全局变量*/init : function(){this.playList = [];    //音乐列表this.currentMusic = 0;  //第一首this.currentMusicInfo = null;this.playMode = 3;      //列表循环播放this.volumeNum = 0;   //音量为0.5this.recordList = [];   //音乐播放记录this.audio = document.createElement('audio');   //播放器对象this.rewriteEvent();this.prevNum = 0;   //仅随机播放时有效,上prevNum首},/*** 将指定路径的歌词转换成数组*/parseLyric : function(lrc){if(!lrc) return '';var data = fs.readFileSync('public/lrc/' + lrc);//这里应该做读取文件出错的处理data = iconv.decode(data, 'gbk');//把数组转换为gbk中文var lyric = data.split('\r\n'), //按行分割lrc = new Array(); //新建一个数组存放最后结果for(var i=0,len=lyric.length,d,t,dt,_t,pt;i<len;i++) {d = lyric[i].match(/\[\d{2}:\d{2}((\.|\:)\d{2})\]/g);  //正则匹配播放时间if( d == null) continue;    //过滤掉空行等非歌词正文部分t = lyric[i].split(d); //以时间为分割点分割每行歌词,数组最后一个为歌词正文dt = String(d).split(':');  //[01:14.48]_t = parseInt(dt[0].split('[')[1])*60 + parseFloat(dt[1].split(']')[0]);_t = _t.toFixed(2); //保留两位小数//判断是否为翻译,//特点:一般翻译的时间和上一行的时间相同,则被认定为翻译//一般歌词的形式为:比如:// [00:04.53]I have nobody// [00:07.13]我一无// [00:07.13]for my owwnnn// [00:10.35]所有 if(pt == d){    //相同的话,将数据保存当上个数组中pt = lrc.length;_t = lrc[pt-1]; //获取最后一个lrc[pt-1] = [_t[0], t[1]];  //将最后一个的中文去掉,将英文赋给第二个元素lrc[pt-2][2] = _t[1];   //将最后一个的中文赋给倒数第二个的第三个元素}else{lrc.push([_t, t[1]]); }pt = d+'';}return lrc;},/*** 根据time从arr中匹配到所在的行* start : 开始遍历的索引* arr 为歌词的数据:比如   [ [ '0.40', 'Lonely\r', '寂寞,\r' ],[ '1.86', 'I\'m Mr Lonely\r', '我是寂寞先生 \r' ]]* time 为要确定的时间:比如 0.40 或者 1,如果时间不匹配,则返回临近时间的小值* return : [ '0.40', 'Lonely\r', '寂寞,\r' ] 的数组索引为:0* 使用条件,数据必须存在,数据的数组[0]必须为时间,time必须为秒形式*/getLrcByTime : function(arr ,time ,start ,end){if(!arr) return -1;if(!start || start == -1) start = 0;time = parseFloat(time);var rindex = 0;for(var i=start;i<end;i++){if(time <= parseFloat(arr[i][0])){if((i-1)<start) rindex = -1 ;   //应该获取上一个else rindex = i-1 ;break;}}return rindex;},/*** 重写播放器的监听事件*/rewriteEvent : function(){var audioDom = this.audio,arg = this.arg,_intPlayingTime,calcTime = Utils.calcTime; //重写播放时的方法...var _onplaying = arg.onplaying;if(typeof(_onplaying) == 'function'){//当媒介已开始播放时运行的脚本。audioDom.onplaying = function(){var self = this ,duration = this.audio.duration;    //总时长if(_intPlayingTime) clearInterval(_intPlayingTime);_intPlayingTime = setInterval(function(){   //循环监听if(self.audio.paused == true){clearInterval(_intPlayingTime);         //取消循环return;}var curtime = self.audio.currentTime;   //当前时间_onplaying((curtime/duration).toFixed(6) ,calcTime(curtime) ,curtime.toFixed(2));if(curtime == duration) clearInterval(_intPlayingTime);},500);//每隔0.5秒,执行if(typeof(arg.onplay) == 'function'){arg.onplay();}}.bind(this);}//当文件就绪可以开始播放时运行的脚本(缓冲已足够开始时)。audioDom.oncanplay = function(){   var duration = this.audio.duration ,musicInfo = this.currentMusicInfo;musicInfo.duration = duration;musicInfo.time = calcTime(duration);if(typeof(this.arg.onstartplay) == 'function'){this.arg.onstartplay(musicInfo); }}.bind(this);//当目前的播放列表已结束时audioDom.onended = function(){this.playByIndex(this.getNextIndexByModel());}.bind(this);//当媒介被用户或程序暂停时运行的脚本。audioDom.onpause = arg.onpause || null; },/*** 得到播放器的状态* 0:正在播放,1:已暂停,[可扩展]*/getMediaStatus : function(){return this.audio.paused == false ? 0 : 1;},/*** 设置音量*/setVolume : function(v){if(!v) return;if(v < 0) v = 0;if(v > 10) v = 10;v = v/10;this.audio.volume = v;},/** * 根据百分比设置当前播放进度*/setCurrentTime : function(percent){if(!this.currentMusicInfo.duration) return;this.audio.currentTime = this.currentMusicInfo.duration * percent;},/*** 根据播放模式和当前音乐的索引,获得下一首的音乐索引*/getNextIndexByModel : function() {var playModel = parseInt(this.playMode),currentNum = this.currentMusic,size = this.playList.length - 1,nextMusicNum;if(playModel == 0){ //'单曲播放'nextMusicNum = -1;}else if(playModel == 1){ //'单曲循环'nextMusicNum = currentNum;}else if(playModel == 2){ //'顺序播放'nextMusicNum = (currentNum+1) > size ? -1 : currentNum+1;//超过最后一首,则不播放}else if(playModel == 3){ //'循环播放'nextMusicNum = (currentNum+1) > size ? 0 : currentNum+1;//超过最后一首,则播放第一首}else if(playModel == 4){ //'随机播放'nextMusicNum = Utils.getRandom(currentNum ,0 ,size);}// console.log('当前模式为:%s\t共有%d首歌曲',this.config.musicMode[playModel],size+1);// console.log('正在播放第'+currentNum+'首');// console.log('将要播放第'+nextMusicNum+'首');return nextMusicNum;},/*** 根据操作数量播放音乐:比如num=1,则播放下一首,-1:播放上一首*/playByNum : function(num){var playList = this.playList ,size = playList.length - 1 ,curNum = this.currentMusic ,nextNum = 0;if(num == 1){nextNum = this.getNextIndexByModel();}else if(num == -1){var recordList = this.recordList,playModel = parseInt(this.playMode),rsize = recordList.length;if(playModel == 0){ //'单曲播放'nextNum = -1;}else if(playModel == 1){ //'单曲循环'nextNum = curNum;}else if(playModel == 2 ){ //'顺序播放'nextNum = (curNum-1) < 0 ? -1 : curNum-1;//超过第一首,则不播放}else if(playModel == 3 ){ //'循环播放' nextNum = (curNum-1) < 0 ? size : curNum-1;//超过第一首,则播放最后一首歌}else if(playModel == 4){ //'随机播放'  -> 从播放记录中取得console.log(recordList);if(rsize <= 1){ //仅播放过一首歌时,nextNum = -1;} else {//这里有错误!var _temp = rsize - 2 - this.prevNum;   //如果是随机播放,则上一首,应该播放列表 - 单击上一首的次数 - 1(长度转成数) - 1(最后一条记录的上一条记录)if(_temp < 0) _temp = 0;nextNum = recordList[_temp].index;this.playByIndex(nextNum ,true ,false); //不添加到播放记录中this.prevNum += 1;return;}}}this.playByIndex(nextNum);},/*** 根据音乐索引播放音乐,比如index=2,就是播放本列表的第二首音乐* 这里触发刚播放音乐时的事件* isplay : 是否播放[默认为是]* isrecord : 是否添加到播放记录列表[默认为是]*/playByIndex : function(index ,isplay ,isrecord){var playList = this.playList;if(index < 0 || index >= playList.length){this.stop();return;}var musicInfo = this.playList[index];//得到歌词,并添加到音乐信息中try{// 0 = HAVE_NOTHING - 没有关于音频/视频是否就绪的信息// 1 = HAVE_METADATA - 关于音频/视频就绪的元数据// 2 = HAVE_CURRENT_DATA - 关于当前播放位置的数据是可用的,但没有足够的数据来播放下一帧/毫秒// 3 = HAVE_FUTURE_DATA - 当前及至少下一帧的数据是可用的// 4 = HAVE_ENOUGH_DATA - 可用数据足以开始播放// console.log(audio.readyState);this.audio.src = musicInfo.source.mp3; }catch (e){console.log('try catch playByIndex:')console.log(e);console.log('\n');}this.currentMusic = index;musicInfo.lrcData = this.parseLyric(musicInfo.lrc);this.currentMusicInfo = musicInfo;if(typeof(this.arg.onswitch) == 'function'){this.arg.onswitch(index); }if(isplay == false) return;this.play();if(isrecord == false) return;this.recordList.push({index:index ,info:musicInfo});},/*** 播放音乐**/play : function(){this.audio.play();},/*** 暂停*/pause : function(){this.audio.pause();},/*** 暂停播放,并重置界面,重置进度*/stop : function(){this.pause();   //暂停播放if(typeof(this.arg.onstop) == 'function'){this.arg.onstop();}this.audio.currentTime = 0;},/*** 重置播放列表**/resetPlayList : function(playList){this.playList = playList;this.audio.volume = this.volumeNum;this.audio.muted = false;this.playByIndex(0 ,false); //播放第一首歌曲}
};


4.最终效果

其实注释掉index.html页面里的require这一段,仅执行music()这个方法,可以直接在谷歌浏览器中看效果
v1.3

项目源码:https://github.com/ymma/node-webkit-MusicBox


http://chatgpt.dhexx.cn/article/HQ2EvUmc.shtml

相关文章

算数计算机音乐模拟器,Musicalculator

musicalculatorapp它是一个音乐旋律软件&#xff0c;在这上面你可以随时随地的记录你有灵感时创作出来的乐谱&#xff0c;还可以放好听的音色包进行自动的弹奏&#xff0c;还可以根据自己的想法设定速度音长&#xff0c;这一款非常的适合喜爱音乐的用户。该应用只是一款音乐计算…

HTML5 CSS3实战——自定义音乐播放器(一)

前几天才刚开始接触HTML5和CSS3。学习了一下里面的一些炫酷的新特性。不过&#xff0c;对于原生的HTML5的媒体播放器&#xff0c;真的不得不吐槽&#xff1a;就三个按钮 界面还那么丑。所以觉得自己整一个好看的播放器。老话说&#xff1a;说不如干&#xff0c;纸上谈兵终觉浅。…

NetEase MusicBox —— Linux系统里的网易云音乐(转载)

功能特性 320kbps的高品质音乐 歌曲&#xff0c;艺术家&#xff0c;专辑检索 网易 22 个歌曲排行榜 网易新碟推荐 网易精选歌单 网易 DJ 节目 私人歌单&#xff0c;每日推荐 随心打碟 本地收藏&#xff0c;随时加 ? 播放进度及播放模式显示 Vimer 式快捷键让操作丝般顺滑 可使…

MusicBox - 仿千千静听

大学毕业时业余之作 最新下载地址&#xff1a; 匿名提取文件连接 http://pickup.mofile.com/5412819180446197 或登录Mofile&#xff0c;使用提取码 5412819180446197 提取文件 MusicBox 停止开发&#xff01;&#xff01; 淘宝开卖源代码 有意者 http://item.taobao.co…

音乐播放器

用HTML做了个音乐播放器&#xff0c;可以循环播放&#xff0c;选择歌曲&#xff0c;以及自动播放下一首&#xff0c;运用了js和json知识&#xff0c;下面是效果图和源码&#xff0c;有兴趣的可以试试哦 效果图&#xff1a; 源码&#xff1a;html <span style"color:#9…

MusicPlay播放器

文章目录 一丶前端布局二丶Activity三丶Service实验演示 一丶前端布局 Layout的框架 一个自定义的音乐播放器&#xff0c;页面布局大致如下 二丶Activity 首先定义控件 // 获取界面中显示歌曲标题、作者文本框TextView title, author;// 喜欢&#xff0c;播放&#xff0c;暂…

MusicPlay 音乐播放器(纯前端)

纯Css,js前端音乐播放器,界面UI比较好。我特别喜欢,适合二次开发,调用了网易云第三方接口以及将歌曲链接导出可以访问的歌曲链接,实现了异步歌曲搜索播放,以及异步显示歌词等.结合html5 新特性实现歌曲暂停,下一首,快进等等.为大二前端练手项目.采用渐变质背景 是前端练手的好…

HTML5+JS实现简易的音乐播放器

HTML5JS实现简易的音乐播放器 播放器实现的功能 播放/暂停音乐切换歌曲&#xff0c;上/下一首歌音量最大或静音音乐播放时间实时变化进度条拖拽歌曲图片切换 播放器效果展示 代码展示 html <div class"musicBox" id"musicBox"><audio src"…

音乐播放器MusicBox

音乐播放器MusicBox 功能界面分析 界面要求较为简洁&#xff0c;仅需两个TextView&#xff0c;用于输出音乐名称及歌手姓名&#xff0c;下方三个ImageButton&#xff0c;用于播放&#xff0c;暂停或切换上一首&#xff0c;下一首歌曲。 实现 总体规划 在MainActivity中&a…

索尼音乐应用android,Sony Music Center

Sony Music Center是全新的索尼音乐中心也是原来的songpal应用&#xff0c;作为sony手机上面的专业播放器的软件&#xff0c;它能够为用户播放各种音乐上面的内容&#xff0c;它可以直接的为用户解析各种音乐的内容&#xff0c;让用户能够随时的在手机上面收听到自己所喜欢的无…

MusicLibrary:一个丰富的音乐播放封装库

code小生,一个专注 Android 领域的技术分享平台 作者&#xff1a;lizixian18链接&#xff1a;https://github.com/lizixian18/MusicLibrary声明&#xff1a;本文是 lizixian18 投稿,转载等请联系作者获得授权。 MusicLibrary 一个丰富的音乐播放封装库&#xff0c;针对快速集成…

MusicBox

MusicBox 编写音乐盒代码&#xff0c;并添加音乐播放的 上一首 和 下一首 控制。 1.添加所需的图片以及音乐文件&#xff1b; 2.编写xml文件&#xff0c;上一首、下一首、暂停、播放按钮以及歌曲的名字和作者 <?xml version"1.0" encoding"utf-8"?&…

Musicplayer

Musicplayer Python 音乐播放器 功能&#xff1a; 首先可以实现本地音乐的播放&#xff0c;能够打开电脑端的文件&#xff0c;文件中进行多选&#xff0c;实现暂停、上一曲、下一曲的功能。在此基础上&#xff0c;完成随机播放列表和网络端下载的功能。 设计方法&#xff1a; 本…

MusicBox(音乐播放器)

这两天做了一个小型的音乐播放器&#xff0c;基本功能都已实现&#xff0c;同时也让我对CSliderCtrl&#xff0c;MCI_OPEN_PARMS以及控件之间的消息映射&#xff0c;数据转换等有了更深入的理解&#xff0c;下面是自己编程的详细过程&#xff1a; 1 首先将控件的位置都摆好&a…

musicbox使用方法_使用Pi MusicBox收听流音乐

musicbox使用方法 在用Raspberry Pi 控制圣诞树灯的项目完成之后&#xff0c;下一个项目是什么&#xff1f; 我最终开始尝试使用Pi Musicbox进行修补&#xff0c;这是Mopidy的Raspbian的一种版本 &#xff0c;它允许用户在“无头”的Raspberry Pi上播放各种流媒体服务&#xff…

推荐一个高大上的网易云音乐命令行播放工具:musicbox

网易云音乐上有很多适合程序猿的歌单&#xff0c;但是今天文章介绍的不是这些适合程序员工作时听的歌&#xff0c;而是一个用Python开发的开源播放器&#xff0c;专门适用于网易云音乐的播放。这个播放器的名称为MusicBox, 特色是用命令行版本执行音乐的播放。 github地址&…

移动开发技术(三)MusicBox

实验要求 使用广播机制&#xff0c;编写音乐盒代码&#xff0c;添加音乐播放的播放、暂停、停止、上一首和下一首控制 实验步骤 一、布局设置 添加一个LinearLayout&#xff0c;选择垂直分布。在里面添加两个LinearLayout&#xff1a; ①music_show&#xff1a;用于展示图片…

Gap Statistic算法详解

在Kmean算法确定K值的问题里&#xff0c;可以使用手肘法&#xff0c;也可以用Gap statistic 算法。手肘法的缺点是不够自动化&#xff0c;而Gap不再需要“手肘法”式的肉眼判断&#xff0c;而只需要找出使Gap Statistic最大的K值即可。因此&#xff0c;Gap和适用于批量化作业。…

IDEA 统计插件Statistic:查看你的代码量

最近接触了一款IDEA统计代码量的插件Statistic&#xff0c;简介一下Statistic的安装。 一、插件下载安装 File->Settings->Plugins&#xff0c;输入Statistic&#xff0c;点击install,安装完后选择重启idea。 二、运行使用 重启完后&#xff0c;点击refesh即可看到代码量…

idea中安装统计代码statistic插件

百度一圈都是直接在idea中安装statistic插件&#xff0c;就不再重复 1.从官网下载&#xff1a;http://plugins.jetbrains.com/plugin/4509-statistic/versions 插件包 到本地 2.选择从本地安装 3. 4.重启idea 5.工具栏