对于喜欢豆瓣FM的同学来说,没有歌词是件令人苦恼的事,下面我就来总结下怎样为豆瓣FM写一个chrome的歌词插件。

---------------------------------

1.需要的技能

首先,你要会javascript,其次你要掌握一点chrome的hack,最后要有一个可以根据歌曲名查到歌词的API。

2.localStorage

localStorage与cookie类似,它是存储在客户端浏览器中的数据,它与cookie不同的一点是它没有时间限制。localStorage属于html5中的新特性。因为我们要做chrome的插件,所以按F12弹出开发者模式,点击resource,就可以看见localstorage选项了,通过localStorage,我们可以得到当前豆瓣播放的歌曲的id,歌曲名,演唱者等信息:

3.歌词迷的API

请求地址: http://geci.me/api/lyric/:song
返回格式: JSON
请求方法: GET
示例:
curl 'http://geci.me/api/lyric/海阔天空'

返回:

{"count": 15,"code": 0,"result": [{ "aid": 2848529, "lrc": "http://s.geci.me/lrc/344/34435/3443588.lrc", "sid": 3443588, "artist_id": 2, "song": "\u6d77\u9614\u5929\u7a7a" },{ "aid": 2346662, "lrc": "http://s.geci.me/lrc/274/27442/2744281.lrc", "sid": 2744281, "artist_id": 2396, "song": "\u6d77\u9614\u5929\u7a7a" },{ "aid": 1889264, "lrc": "http://s.geci.me/lrc/210/21070/2107014.lrc", "sid": 2107014, "artist_id": 8715, "song": "\u6d77\u9614\u5929\u7a7a" },{ "aid": 2075717, "lrc": "http://s.geci.me/lrc/236/23651/2365157.lrc", "sid": 2365157, "artist_id": 8715, "song": "\u6d77\u9614\u5929\u7a7a" },{ "aid": 1563419, "lrc": "http://s.geci.me/lrc/166/16685/1668536.lrc", "sid": 1668536, "artist_id": 9208, "song": "\u6d77\u9614\u5929\u7a7a" },{ "aid": 1567586, "lrc": "http://s.geci.me/lrc/167/16739/1673997.lrc", "sid": 1673997, "artist_id": 9208, "song": "\u6d77\u9614\u5929\u7a7a" },{ "aid": 1571906, "lrc": "http://s.geci.me/lrc/167/16796/1679605.lrc", "sid": 1679605, "artist_id": 9208, "song": "\u6d77\u9614\u5929\u7a7a" },{ "aid": 1573814, "lrc": "http://s.geci.me/lrc/168/16819/1681961.lrc", "sid": 1681961, "artist_id": 9208, "song": "\u6d77\u9614\u5929\u7a7a" },{ "aid": 1656038, "lrc": "http://s.geci.me/lrc/179/17907/1790768.lrc", "sid": 1790768, "artist_id": 9208, "song": "\u6d77\u9614\u5929\u7a7a" },{ "aid": 1718741, "lrc": "http://s.geci.me/lrc/187/18757/1875769.lrc", "sid": 1875769, "artist_id": 9208, "song": "\u6d77\u9614\u5929\u7a7a" },{ "aid": 2003267, "lrc": "http://s.geci.me/lrc/226/22642/2264296.lrc", "sid": 2264296, "artist_id": 9208, "song": "\u6d77\u9614\u5929\u7a7a" },{ "aid": 2020610, "lrc": "http://s.geci.me/lrc/228/22889/2288967.lrc", "sid": 2288967, "artist_id": 9208, "song": "\u6d77\u9614\u5929\u7a7a" },{ "aid": 2051678, "lrc": "http://s.geci.me/lrc/233/23323/2332322.lrc", "sid": 2332322, "artist_id": 9208, "song": "\u6d77\u9614\u5929\u7a7a" },{ "aid": 2412704, "lrc": "http://s.geci.me/lrc/283/28376/2837689.lrc", "sid": 2837689, "artist_id": 9208, "song": "\u6d77\u9614\u5929\u7a7a" },{ "aid": 2607041, "lrc": "http://s.geci.me/lrc/311/31116/3111659.lrc", "sid": 3111659, "artist_id": 9208, "song": "\u6d77\u9614\u5929\u7a7a" }]
}


4.重头戏----javascript脚本


有了上面的准备工作,我们现在就可以安心的编码了。

首先,创建一个DoubanFM伪类(javascript中没有“真正的”类)

funciton DoubanFM() {this.name = '豆瓣FM';this.tmp_song_id = '';this.flag = 1;this.lyrics = this.draw_lyrics();
}

然后,对这个伪类拓展原型,创建新的函数:

【注】关于javascript拓展函数原型,我原来写过一篇博客:http://blog.csdn.net/wusuopubupt/article/details/14520209

用javascript创建新的节点(一个显示歌词的div,同时设置div的css):

DoubanFM.prototype.draw_lyrics = funciton() {var lyrics_div = document.createElement('div');//用document.createElement()方法可以创造新的节点document.body.appendChild(lyrics_div);//用document.body.appendChild()方法把新的节点附加到到document中lyrics_div.style.width = '900px';//下面几行是设置csslyrics_div.style.backgroundColor = '#F00';lyrics_div.style.zIndex = '42';lyrics_div.style.position = 'relative';lyrics_div.style.margin = '200px auto 0';return lyrics_div;
}

根据localstorage里获取的信息,构造获取歌词的url:

DoubanFM.prototype.geci_entry_url = function(song, artist) {if (song == undefined || song == null || song == '') return '';var url = 'http://geci.me/api/lyric/' + song;if (!(artist == undefined || artist == null || artist == '')) {url += '/' + artist;}console.log(url);return url;
}

用AJAX方式异步请求歌词:

Douban.prototype.request_geci = function() {eval('var stored_song = ' + localStorage['bubbler_song_info']);//这里是重点,localstorage!console.log('the song in localStorage:' + stored_song.artist + ' ' + stored_song.song_name);if (this.tmp_song_id != stored_song.id) {console.log(this.tmp_song_id + ' is not ' + stored_song.id);var url = this.geci_entry_url(stored_song.song_name, stored_song.artist);this.tmp_song_id = stored_song.id;this.ajax_get(url);}
}

ajax请求:

DoubanFM.prototype.ajax_get = function(url) {var XHR = new XMLHttpRequest();var obj = this;//一次典型的原生js发起的AJAX请求XHR.onreadystatechange = function() {if (XHR.readyState == 4) {if (XHR.status == 200) {obj.deal_response(XHR.responseText);} else {obj.print_lyrics('获取歌词失败');}} else {obj.print_lyrics('歌词搜索中');}}XHR.open('GET', url, true);XHR.send();
}DoubanFM.prototype.deal_response = function(data) {if (this.flag == 1) {eval('var resp = ' + data);if (resp.count > 0) {this.ajax_get(resp.result[0].lrc);this.flag++;} else {this.print_lyrics('没有找到歌词');}} else {this.print_lyrics(this.format(data));this.ajax_flag = 1;}
}

对返回的歌词做处理:

DoubanFM.prototype.format = function(text) {var s = text.replace(/\[(.*)\]/g, '').trim();//去除返回数据的[]两端的内容,只保留歌词部分return s.replace(/\n/g, '\n<br />');//每行末尾输出html的换行符
}

把format过后的歌词显示在上面用document.createElement()方法创建出来的div中:

DoubanFM.prototype.print_lyrics = function(text) {this.lyrics.innerHTML = '<div id="mylrc" style="width: 490px; max-height: 280px; padding:10px; background-color: #9dd6c5; z-index: 42; po   sition: absolute; right: 0; overflow-x: hidden; overflow-y: scroll; display: block;">'+ text +'</div>';
}

最后,用setInterval()方法,每隔一秒执行就获取歌词的方法,实现豆瓣FM歌词的更新和显示:

var  fm = new DoubanFM(true);
window.setInterval(function() { fm.request_geci(); }, 1000);

至此,javascript的工作就完成了。

5.还需要什么?


写一个chrome的插件,你还需要一个manifest.json文件,类似这样:

{"name" : "Douban FM 歌词","version" : "1.0","manifest_version" : 2,"description" : "Douban FM Lrc","page_action" : {"default_icon" : "icon.png","default_title" : "Douban FM 歌词"},"permissions" : ["tabs", "http://douban.fm/", "http://*.geci.me/*"],"background" : {"scripts" : ["background.js"]},"content_scripts" : [{"matches" : ["http://douban.fm/"],"js" : ["lyrics.js"],"runat" : "document_end"}],"icons" : {"48" : "icon-48.png","128" : "icon-128.png"}
}

还需要几个不同size的icon,类似这样:

 

最后,到chrome的拓展程序(直接在地址栏输入:chrome://extensions/),选择“打包拓展程序”,然后把我们的整个程序的文件夹选中,即可生成一个.crx文件,拖进chrome,即可安装。

:如果你想好好学下如何制作chrome的拓展,可以看这篇文章:http://www.cnblogs.com/walkingp/archive/2011/03/31/2001628.html

6.最后的效果


在我们的拓展程序中,可以看到:

再进入豆瓣FM,听听歌,哦,我看到歌词啦!

7.参考:


1).http://www.v2ex.com/t/54570

2).http://www.douban.com/note/282160723/?type=like

如何为豆瓣FM写一个chrome的歌词插件相关推荐

  1. 如何写一个Jquery 的Plugin插件

    JQuery Plugin插件,如果大家不明白什么是JQuery插件或都不清楚如何编写可以查看其官方的网站:jQuery Authoring Guidelines 好了,下面有一些我觉得想做一个好的插 ...

  2. 手写一个Vuex的持久化插件

    前两天做了个vue的项目,为了避免刷新后数据全部恢复原样,在项目中使用了 vuex-persistedstate 这个持久化插件,在这个项目中需要借助这个插件主要实现的功能是:将需要持久化的数据存储并 ...

  3. 豆瓣 FM 精美版 Chrome 扩展:改变的不只是外表

    网页版豆瓣FM经过改版之后在界面上比之前的版本明显给力了很多,但是扩展的好处永远存在,它不用切换标签卡,而且比网页版要轻量级.但是基于豆瓣FM的扩展已经有很多了,为什么还要费力气再做一份呢?因为,这个 ...

  4. python写chrome插件_用VueJS写一个Chrome浏览器插件

    浏览器基本已经天下大统了,放眼望去都是Chromium的天下.那么,能写一个浏览器插件也算是一种回报率不错的技能. 基本知识 浏览器插件官方的说法叫扩展程序,允许你为浏览器增加各种功能,但不需要深入研 ...

  5. 跟我一起写一个chrome扩展程序

    在我没有看这本书之前,我都想象不到,原来chrome扩展程序可以这样写,真的非常有意思. 就是用最简单最基础的代码,然后就实现了一些非常有意思的玩意儿. 先看效果图 实际运用要和现实联系在一起,经历和 ...

  6. 简单说 如何做一个chrome 去广告插件

    说明 Chrome插件又称为谷歌浏览器插件,是谷歌Chrome浏览器的扩展插件,使用Chrome插件可以为Chrome浏览器带来一些功能性的扩展,进而提高Chrome的使用体验. 这次我们先来简单接触 ...

  7. python wx包_今天玩点啥:python真香系列之利用wxpy包写一个微信消息自动回复插件...

    阅读本文假设你本地已经安装了Python3基础环境. 安装wxpy模块: pip3 install wxpy 添加以下代码即可实现扫码登录 # 导入模块 from wxpy import * # 初始 ...

  8. 简单几行代码,写一个百度广告屏蔽插件,爽到爆

    下载地址:https://github.com/jsoncode/b... 使用方法: 将文件夹拖到这里面 一个小问题: 我没有境外支付信用卡>无法向谷歌支付$5的费用>每次打开浏览器都会 ...

  9. 写一个Flutter手势追踪插件

    /   今日科技快讯   / 近日字节跳动组织升级,张利东担任字节跳动(中国)董事长,全面协调公司运营,包括字节跳动中国的战略.商业化.公共事务.公共关系.财务.人力:抖音CEO张楠将担任字节跳动(中 ...

最新文章

  1. 概要设计实例_多核片上系统(SoC)架构的嵌入式DSP软件设计
  2. SAP 前端技术的演化史简介
  3. mysql 唯一约束 多字段_mysql多字段唯一约束
  4. 拔掉数据库的电源会怎样?阿里云数据库新型灾备架构,让云端容灾有“备”无患
  5. python画鱼_Python经典五人分鱼实例讲解
  6. SpringBoot2.0之五 优雅整合SpringBoot2.0+MyBatis+druid+PageHelper
  7. PWDX查找程序执行路径
  8. Java JDBC------------------ODBC(SQLServer)链接
  9. clickhouse数据字典
  10. vb adodc连接mysql_VB之Adodc控件连接数据库
  11. 图片合并pdf,详细方法!
  12. html中获取浏览器窗口宽度,JavaScript 获取浏览器窗口的大小
  13. 【华为】verilog语言编写规范(一)
  14. matlab function调用m文件,matlab下编写和调用函数(在同一个m文件中)
  15. Vue 实现附件上传
  16. ASF 董事会是如何炼成的?
  17. 【RMAN】RMAN跨版本恢复(中)
  18. 问题条件数(Conditioning of a problem)
  19. android微信升级后还原,安卓微信好友一键恢复靠谱吗,微信一键还原后果
  20. Android 属性动画(一)新手入门

热门文章

  1. 你可能会读错的字大集合
  2. unity简单计时器_简单且悦目的Pomodoro计时器
  3. Python中的数据序列(元组、集合、字典)
  4. 弗洛伊德、荣格、阿德勒
  5. Python-基础课-第二节-02-变量与常量
  6. 彩色飘带字体怎么制作?AE教程教给你
  7. Element-UI学习之旅-Border边框及图标
  8. 壮大云平台中国力量 安全可控大会即将登场
  9. 数据挖掘机器学习及其他领域数据集汇总
  10. oracle 12c 归档模式,Oracle 12c 归档模式更改