专栏首页蜉蝣禅修之道Chrome插件开发之制作豆瓣电台歌词

Chrome插件开发之制作豆瓣电台歌词

http://blog.csdn.net/wusuopubupt/article/details/21083775得到的启发,在周末自己抽空也做了一个插件,也顺便补充一下po主的教程。

准备工作:正如http://blog.csdn.net/wusuopubupt/article/details/21083775提及,我们需要JavaScript开发基础,chrome插件开发基础,本人第一次开发chrome插件,所以首先恶补了一上午,再者我们还需要知道从哪里根据歌曲名和歌手名获取歌词,感谢po主给我们推荐了http://geci.me/api/lyric/,这个好用的接口,我们可以在url后加上‘歌曲名/歌手名’从而获得歌词的json信息。如下是http://geci.me/api/lyric/listen,得到的信息:

{
  "count": 8,
  "code": 0,
  "result": [
    {
      "aid": 2574902,
      "lrc": "http://s.geci.me/lrc/306/30660/3066099.lrc",
      "song": "Listen",
      "artist_id": 2762,
      "sid": 3066099
    },
    {
      "aid": 1814321,
      "lrc": "http://s.geci.me/lrc/200/20048/2004871.lrc",
      "song": "Listen",
      "artist_id": 15735,
      "sid": 2004871
    },
    {
      "aid": 2741204,
      "lrc": "http://s.geci.me/lrc/329/32975/3297582.lrc",
      "song": "Listen",
      "artist_id": 25266,
      "sid": 3297582
    },
    {
      "aid": 3232739,
      "lrc": "http://s.geci.me/lrc/395/39566/3956629.lrc",
      "song": "Listen",
      "artist_id": 32473,
      "sid": 3956629
    },
    {
      "aid": 2922563,
      "lrc": "http://s.geci.me/lrc/354/35450/3545085.lrc",
      "song": "Listen",
      "artist_id": 34747,
      "sid": 3545085
    },
    {
      "aid": 3003590,
      "lrc": "http://s.geci.me/lrc/365/36514/3651490.lrc",
      "song": "Listen",
      "artist_id": 34747,
      "sid": 3651490
    },
    {
      "aid": 3182564,
      "lrc": "http://s.geci.me/lrc/388/38895/3889558.lrc",
      "song": "Listen",
      "artist_id": 35285,
      "sid": 3889558
    },
    {
      "aid": 3131255,
      "lrc": "http://s.geci.me/lrc/382/38223/3822392.lrc",
      "song": "Listen",
      "artist_id": 39213,
      "sid": 3822392
    }
  ]
}

此外,我们需要知道如何获得豆瓣电台当前歌曲信息,感谢po主的发现,我们可以在localstorage中找到歌曲名和歌手名,如下图所示

好了,准备工作做好了,进入正题吧。我们这次是开发基于page_action的chrome插件,不知道的同学,可以上chrome插件开发文档看看。

以下是本项目的文件结构:

开发插件第一步是写manifest.json

{
    "name": "Douban FM Lyric",
    "version": "1.0",
    "manifest_version": 2,
    "description": "The lyric extension of the douban.fm",
    "page_action": {
        "default_icon": "img/icon.jpeg",
        "default_title": "Dave's Douban FM lyric"
    },
    "background": {
        "scripts": ["js/background.js"]
    },
    "content_scripts": [
        {
            "matches": ["http://douban.fm/*"],
            "js": ["js/jquery-1.11.0.min.js", "js/lyrics.js"],
            "runat": "document_end"
        }
    ],
    "permissions": [
        "tabs", "http://douban.fm/*", "http://geci.me/api/lyric/*","http://*.geci.me/*"
    ]
}

content_scripts和permissions比较重要,规定了本插件匹配的页面以及需要访问的网站。

第二步,content_scripts,插件与豆瓣电台主要交互是在lyrics.js,以下所有代码都在lyrics.js里。

创建Song伪类,定义属性:

function Song(id, name, artist) {
    this.id = id;
    this.name = name;
    this.artist = artist;
    this.lyricUrl;
    this.lyric = this.addLyric();
}

添加伪类方法,定义歌词div,嵌入电台页面。

Song.prototype.addLyric = function () {
    var lyrics_div=document.createElement('div');//用document.createElement()方法可以创造新的节点
    document.body.appendChild(lyrics_div);//用document.body.appendChild()方法把新的节点附加到到document中
    lyrics_div.style.width = '900px';//下面几行是设置css
    lyrics_div.style.backgroundColor = '#F00';
    lyrics_div.style.zIndex = '42';
    lyrics_div.style.position = 'relative';
    lyrics_div.style.margin = '200px auto 0';
    lyrics_div.id = 'lyricParent';
    lyrics_div = $('<div id="myLyric" style="width: 490px;height: 280px;background-color: #9dd6c5;position: absolute;right: 0;overflow: auto;display: block;font-size: 14px;padding: 10px;"></div>')
    $('div#lyricParent').append(lyrics_div);
    return lyrics_div;
}

Ajax获取歌词url,首先用歌曲名+歌手名准确查找歌词,如果没有,去掉歌手名再查找一次。

Song.prototype.getLyricUrl = function () {
    var withAritist = false;
    if (this.name == undefined || this.name == null || this.name == '') return '';
    var url = 'http://geci.me/api/lyric/' + this.name;
    if (!(this.artist == undefined || this.artist == null || this.artist == '')) {
        url += '/' + this.artist;
        withAritist = true;
    }
    this.ajaxLyricUrl(url, withAritist);
}
Song.prototype.ajaxLyricUrl = function (url, withAritist) {
    var song = this;
    $.ajax({
        url: url,
        method: 'GET',
        success: function (data) {
            console.log(data);
            var count = data.count;
            console.log(count);
            if (count > 0) {
                song.lyricUrl = data.result[0].lrc;
                song.getLyric();
            } else {
                if (withAritist) {
                    url = url.substring(0, url.lastIndexOf("/"));
                    song.ajaxLyricUrl(url, false);
                } else
                    song.printLyric('找不到歌词');
            }
        },
        error: function () {
            return undefined;
        }
    })
}

Ajax获取歌词,把时间信息去掉,把换行符替换成\n<br>

Song.prototype.getLyric = function () {
    var url = this.lyricUrl;
    var song = this;
    $.ajax({
        url: url,
        method: 'GET',
        success: function (data) {
            //将时间信息去掉,g全局符号,把所有匹配字符串替换
            data = data.replace(/\[.*\]/g, '').trim();
            data = data.replace(/\n/g, '\n<br>');
            song.printLyric(data);
        }
    })
}

打印歌词

Song.prototype.printLyric = function (text) {
    this.lyric.html(text);
}

接着,我们给页面嵌入一个Song对象以及一个保存上一首歌的id的变量,其中我监听了豆瓣电台的频道滚动事件,因为我发现频道的滚动好像拦截了该页面所有滚动事件,如果不添加该监听,我们没办法在歌词div里使用滚轮,虽然可以看到滚动条,但是相当不爽啊。即使这样,歌词滚动的实现也不好,因为有时歌词太长,无法滚动到最后一行,只能用滚动条拖动,这对于MacBook使用者简直不能忍,触摸板就像废了一样,希望大家给出更好地建议。

var lastSongId = '', song;
$(document).ready(function () {
    eval('var data=' + localStorage['bubbler_song_info']);
    song = new Song(data.id, data.song_name, data.artist);
    $("div#fm-channel-list").scroll(function () {
        var offsetTop = $(this).scrollTop();
        $("div#myLyric").scrollTop(offsetTop);
    });
})

最后,我们需要创建一个定时器,每2秒检查一下,是不是换歌了,因为电台使用flash插件进行播放的,所以无法直接从页面实时获取歌曲变化情况,只能不断检查localstorage变化情况,蛋疼。。。

window.setInterval(function () {
    eval('var data=' + localStorage['bubbler_song_info']);
    if (lastSongId != data.id) {
        lastSongId = data.id;
        song.setId(data.id);
        song.setArtist(data.artist);
        song.setName(data.song_name);
        song.getLyricUrl();

    }
}, 2000);

插件运行效果:

至此,主要代码已经写完,虽然写得有点复杂,不过最后实现了在别人页面嵌入自己代码还是蛮有成就感的,以后还会开发更多更有用的插件,谢谢,希望本博文对大家有帮助。

代码和打包后的插件下载地址:http://download.csdn.net/detail/xanxus46/7127063

插件安装:

首先打开扩展程序页面:

然后把下载压缩包里的douban lyric.crx拖到扩展程序的页面里安装,然后打开豆瓣就能看到效果了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 如何为豆瓣FM写一个chrome的歌词插件

    forrestlin
  • Extjs自定义多字段VTypes

    forrestlin
  • Ubuntu16.04安装分区设置

    Ubuntu安装过程中,磁盘分区是我们头疼的环节,如果直接按照安装程序推荐总感觉分得不太对,磁盘用着用着就不够用了,特别是装双系统的情况下,本文介绍一下笔者的分...

    forrestlin
  • 零基础html5+div+css+js网页开发教程第010期 图片轮播案例

    用来显示图片的标签。它的Src属性用来设置图片来源,其实也可以直接设置width来设置图片的宽度,设置height来是指图片的高度。值得注意的是,图片的宽度一旦...

    刘金玉编程
  • 资源 | Facebook 17 篇 ECCV 2018 录用论文打包

    计算机视觉领域在深度学习时代高速发展,无论是新任务的探索还是已有任务的新方法都不断出现有趣的新成果。Facebook 人工智能研究院 (Facebook AI ...

    AI研习社
  • 根据表格特定列的内容来追加图标 原

    (adsbygoogle = window.adsbygoogle || []).push({});

    tianyawhl
  • 单点系统架构的可用性与性能优化

    一、需求缘起 明明架构要求高可用,为何系统中还会存在单点? 回答:单点master的设计,会大大简化系统设计,何况有时候避免不了单点 在哪些场景中会存在单点?先...

    架构师之路
  • MySQL add/drop字段时报主键冲突

    错误提示是主键冲突,但是当我们去查询 id= 7458421 时,并无此记录。是不是很奇怪?遇到这种情况,一般有如下场景:

    用户1278550
  • 有关用户留存模型的一种设计方法

    没错,我的工种就是属于那种史上被人吐槽为最没技术含量、最打杂的工种——数据仓库开发工程师。

    数据仓库践行者
  • 程序员的花样编程,你到底行不行?

    【导读】:说到 C/C++ 代码技巧,也许会有童鞋说 ,这是属于 C/C++ 程序员离职前恶搞之类的抖机灵。即便想,也不能干。别忘了有这样一句编程名言:「在编写...

    企鹅号小编

扫码关注云+社区

领取腾讯云代金券