ニコニコ漫画

  • /*
     * @title ニコニコ漫画
     * @description Flash Player がない環境でニコニコ漫画を見る
     * @include http://seiga.nicovideo.jp/watch/mg*
     * @license MIT License
     */
    
    (function($){
    
    var id = location.href.match(/http:\/\/seiga\.nicovideo\.jp\/watch\/mg([0-9]+)/)[1];
    var images = [{}];
    var i = Number(location.hash.substring(1) || 1);
    
    var comments = {};
    
    var audios = {};
    var bgm;
    var se;
    
    var img = $("<img></img>").css({ float: "left", width: "670px", height: "380px", border: "solid 1px #000" });
    var mask = $("<div></div>").css({ position: "absolute", border: "solid 1px #000", "background-color": "#000", "z-index": "100", opacity: "0.5" }).appendTo("body");
    var div = $("<div></div>").css({ float: "left", width: "200px", height: "380px", border: "solid 1px #000", overflow: "scroll" });
    var ol = $("<ol></ol>");
    
    var find_image = function () {
        var id = $(this).find("id").text();
        comments[id] = [];
        var url = $(this).find("source_url").text();
        var bgm_id = $(this).find("bgm_id").text();
        if (bgm_id == -1) {
            bgm_id = undefined;
        } else {
            if (bgm_id) {
                if (!audios[bgm_id]) {
                    var bgm_path = $(this).find("bgm_path").text();
                    var audio = new Audio("http://lohas.nicoseiga.jp" + bgm_path);
                    audio.load();
                    audio.loop = ($(this).find("bgm_loop").text() == 1);
                    audio.volume = 0.2;
                    audios[bgm_id] = audio;
                }
            } else {
                bgm_id = images[images.length - 1]["bgm_id"];
            }
        }
        var se_id = $(this).find("se_id").text();
        if (se_id) {
            if (!audios[se_id]) {
                var se_path = $(this).find("se_path").text();
                var audio = new Audio("http://lohas.nicoseiga.jp" + se_path);
                audio.load();
                audio.volume = 0.2;
                audios[se_id] = audio;
            }
        } else {
            se_id = undefined;
        }
        images.push({ id: id, url: url, bgm_id: bgm_id, se_id: se_id });
    };
    
    var find_comment = function () {
        var image_id = $(this).find("image_id").text();
        var content = $(this).find("content").text();
        var frame = $(this).find("frame").text();
        comments[image_id].push({ content: content, frame: frame  });
    };
    
    var load_image = function (url) {
        var deferred = $.Deferred();
        $(img)
            .on("load", function () { deferred.resolve(); })
            .attr("src", url);
        return deferred.promise();
    };
    
    var append_comment = function (image_id) {
        var ol = $("<ol></ol>").appendTo(div.empty());
        $.each(comments[image_id], function () {
            ol.append($("<li></li>").text(this["content"]));
        });
    };
    
    var play_bgm = function (bgm_id) {
        var deferred = $.Deferred();
        if (bgm != audios[bgm_id]) {
            if (bgm) bgm.pause();
            bgm = audios[bgm_id];
            if (bgm) {
                bgm.addEventListener("play", function () { deferred.resolve(); });
                bgm.load();
                bgm.play();
            } else {
                deferred.resolve();
            }
        } else {
            deferred.resolve();
        }
        return deferred.promise();
    };
    
    var play_se = function (se_id) {
        var deferred = $.Deferred();
        if (se) se.pause();
        se = audios[se_id];
        if (se) {
            if (bgm) se.addEventListener("ended", function () { bgm.play(); });
            se.addEventListener("play", function () { deferred.resolve(); });
            se.load();
            se.play();
        } else {
            deferred.resolve();
        }
        return deferred.promise();
    };
    
    var go_next = function () {
        $.get(
            "/api/theme/next?id=" + id,
            function (xml, status) {
                if (status != "success") return;
                var next = $(xml).find("next");
                var title = next.find("title").text();
                if (title && window.confirm(title)) {
                    location.href = "http://seiga.nicovideo.jp/watch/mg" + next.find("id").text();
                }
            }
        );
    };
    
    $.ajax({
        url: "/api/theme/data?theme_id=" + id,
        converters: {
            "text xml": function (res) {
                res = res.replace(/[\x00-\x1f]/g, "");
                return $.parseXML(res);
            }
        },
        success: function (xml, status) {
            if (status != "success") return;
            $(xml).find("image").each(find_image);
            $(xml).find("comment").each(find_comment);
            $("#playerBody")
                .empty()
                .width(900)
                .append(img)
                .append(div);
            img
                .attr("src", images[i]["url"])
                .click(function (e) {
                    var w = $(this).width();
                    var x = e.pageX - $(this).offset().left;
                    if (x < w / 2) {
                        if (1 < i) { i--; } else { return; }
                    } else {
                        if (images[i + 1]) { i++; } else { go_next(); return; }
                    }
                    location.hash = "#" + i;
                    append_comment(images[i]["id"]);
                    mask.show();
                    $.when(
                        load_image(images[i]["url"]),
                        play_bgm(images[i]["bgm_id"]),
                        play_se(images[i]["se_id"])
                    ).done(function () { mask.hide(); })
                });
            append_comment(images[i]["id"]);
            mask
                .offset(img.offset())
                .width(img.width())
                .height(img.height())
                .on("click", function () {
                    $(this).hide().off("click");
                    play_bgm(images[i]["bgm_id"]);
                    play_se(images[i]["se_id"]);
                });
        }
    });
    
    })(jQuery);
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。

History

  1. 2013/09/03 18:45:41 - 2013-09-03
  2. 2013/08/09 20:20:17 - 2013-08-09
  3. 2013/08/09 19:17:46 - 2013-08-09
  4. 2013/08/08 20:26:36 - 2013-08-08
  5. 2013/08/08 01:06:01 - 2013-08-08
  6. 2013/08/07 18:25:39 - 2013-08-07
  7. 2013/08/06 20:40:48 - 2013-08-06
  8. 2013/08/06 19:32:03 - 2013-08-06
  9. 2013/08/05 19:01:10 - 2013-08-05
  10. 2013/08/05 02:00:30 - 2013-08-05
  11. 2013/08/03 23:55:44 - 2013-08-03
  12. 2013/08/03 23:48:24 - 2013-08-03
  13. 2013/08/03 22:44:22 - 2013-08-03