HTML
CSS
JavaScript
レスポンシブ
漫画

サイトにアップした漫画を読みやすくするライブラリ

comic-viewer

comic-viewer は個人サイトに漫画をアップする際に便利なライブラリになります。
https://github.com/tomalatte001/comic-viewer

漫画を自分のサイトにアップするのってけっこう面倒なんですよね。
1ページにたくさん画像あると重くなりますし、PCとスマホの両方を考慮しないといけなかったり、ブラウザのウインドウサイズも考慮したり。
それに最初のページを見ただけで離脱する方も多いので、何十ページもある画像を全部一度にダウンロードさせるのも無駄な負荷になったりします。

導入方法

そこでこの comic-viewer の JS と CSS を使うと簡単に漫画をアップできるようになります。
GitHub 上のソースをダウンロードし、sample のHTML内の下記の hidden のパラメータの値をするのと、指定したディレクトリに画像をアップ。あとはヘッダーとフッターの文言や色など調整するだけで導入できます。

<input id="comic-dir-large" type="hidden" name="dir-large" value="/sample/images/large">
<input id="comic-dir-small" type="hidden" name="dir-small" value="/sample/images/small">
<input id="comic-extension" type="hidden" name="extension" value="jpg">
<input id="comic-loading" type="hidden" name="loading" value="/images/loading.gif">
<input id="comic-page-count" type="hidden" name="count" value="10">
<input id="comic-page-start" type="hidden" name="start" value="l">
<input id="comic-title" type="hidden" name="title" value="esper hunter">
name 内容
dir-large PC用の大きめの漫画の画像ファイルを保存するディレクトリ
dir-small スマホ用の小さ目の漫画の画像ファイルを保存するディレクトリ
extension 画像ファイルの拡張子
loading 画像読み込み中のローディング画像のパス
count 漫画のページ数
start 漫画の1ページ目が左ページから始まるか、右ページから始まるか(l or r)
title 漫画のタイトル

仕様

PCでは左右に読み進める仕様、スマホでは縦スクロールで読み進める仕様となっています。
スマホでは画面表示時に全ての画像を取りにいってしまいますが、スマホ用に小さ目の画像をアップすることで負荷を軽減できます。
また、PC版ではウインドウのリサイズに合わせて画像が可変になっています。

実装

ライブラリは、jQuery を使わせていただいています。

リサイズ時の処理

comic-viewer.js
    var windowHeight = $(window).height();
    var headerHeight = $('#header-comic').outerHeight(true);
    var footerHeight = $('#footer-comic').outerHeight(true);
    var contentsHeight = windowHeight - headerHeight - footerHeight;
    $('#comic-viewer').css('height', contentsHeight + 'px').css('margin-top', headerHeight + 'px');

ヘッダーとフッターを position:fixed で固定しているので、そのサイズを取得。
画像表示部分をヘッダーとフッターの間に収めています。そのため、ユーザによりヘッダーとフッターのサイズが変わっても問題ありません。

遅延ロード

遅延ロードは、jquery.lazyload.js を使用させていただきました。

comic-viewer.js
    comic.setJustifyContent(this.param.rightPage.parent(), 'center');
    this.param.rightPage.attr('src', loadingPath);
    this.param.rightPage.attr('data-original', rightPath);
    this.param.rightPage.lazyload({load: function() {
        var self = $(this);
        comic.setJustifyContent(self.parent(), 'flex-start');
        return false;
    }});

上記のように、読み進めた場合の画像表示時は img タグの src 属性にローディング画像を一度セットし、data-original 属性に画像のパスをセットしてます。
CSSで漫画画像の左ページは右寄せ、右ページは左寄せ(左右のページが真ん中でくっつくように)にしたのですが、ローディング画像は中央寄せしたかったので、最初に justify-content に center を指定し、画像読み込み完了時にコールバックで再設定してます。

comic.setJustifyContent の実装は下記です。
ブラウザによって、display:flex の設定が異なるようだったので、それぞれの差をここで吸収するようにしました。
ただ、網羅できているわけではないかと思います。

comic-viewer.js
    comic.setJustifyContent = function(target, value) {
        var val = value;
        var webkitVal = value;
        var msVal = value;
        if (value == 'flex-start') {
            msVal = 'start';
        }
        if (value == 'flex-end') {
            msVal = 'end';
        }
        target.css({'justify-content' : val, '-webkit-justify-content' : webkitVal, '-ms-flex-pack' : msVal});
    };

PC とスマホの分岐

comic-viewer.js
    var windowWidth = $(window).width();
    if (windowWidth > 750) {
        comic.pcInit();
    } else {
        comic.spInit(windowWidth);
    }

pcInit がPC用の処理、spInit がスマホ用の処理ですが、上記のように750px で分けました。
調べたところ、最近の iphone が750px あるらしい?と見たので。
スマホにウインドウサイズを渡しているのは、スマホのウインドウ内に画像を収めるように設定するためです。

さいごに

まだ改善の余地はありそうですが、これで漫画ページをだいぶ導入しやすくできたかなと。