Comic-Leader


Anchor


About

Webコミックや連続した画像ファイルを読むのをお手伝いする JavaScript です。

Read (読む) と Lead (導く) をかけて Comic-Leader にしました。
目的とスクリプト自体はすごい車輪の再発明っぽいけど、気にしちゃダメですヨ。

わかりやすく使いやすいインターフェイスを提供するユーザーライクさと、 必要な全ての設定をHTML内で行え、インターフェイスも作者がある程度好きに作れる、 といった割と融通の利くオーナーライクさが、 一番の主眼であり特徴です。 (……ただ、その分いつものように無駄も多いかも)

まあ、過度の宣伝もアレだし、一見に如かないので、 まずは サンプル をご覧ください。

Windows + InternetExplorer-6.0, FireFox-1.0, Opera-7.0 で動作確認。
DOMがまともに使えないような古いブラウザだと動きません。対応する気もございません。

また、 カヤさん が記事の中でちらりと Comic-Leaderの紹介 をしてくれてたりしたので、そちらも参考にしてみてください。(感謝!)

しかし、第三者さんの紹介って、 どうしてこう自分で紹介するよりもずっと興味深いものになるのでしょうね。


History

2005/11/22 (ver1.6)
先読みするページ数を制限できるようにしました.
詳しくは、 HTMLのサンプルソース説明や仕様のメモprelimit の項を、 自作自演 Q&A に 「画像を先読みすると重くなる?」 の項を追加しましたので、そちらをどうぞ.
2005/09/27 (ver1.51)
function preload 周りをちょっと修正.
2005/09/25 (ver1.5)
preload の要素があれば、 先読みしたページをそこに次々に代入していく機能を追加. (→ Specs)
2005/09/24 (ver1.44)
フレームのときの、URL情報からの設定の指定の仕方を変更. (→ Q&A)
2005/09/17 (ver1.43)
ちょっとミスって動作しないのUPしてましたごめんなさい.
ついでに、"一気に表示"にするとき、 件数が多いとブラウザが重くなるので、分割処理にして軽く.
2005/09/11 (ver1.42)
first値とlast値が取得失敗したとき、 それぞれの値を 1 , 999 に.
2005/09/10 (ver1.41)
フォーカスの当て方をちょぴっと変更.
2005/09/09 (ver1.4)
"見開き" に "全ページを羅列" 機能を追加.
2005/09/08 (ver1.3)
キー・ジェスチャー機能を追加.
2005/09/07 (ver1.2)
スクリプト修正. いろんな機能を追加. 設定は画像から全て自動取得に.
2005/09/02 (ver1.1)
クッキー機能追加
2005/09/01 (ver1.0)
ひとまず完成

Sample


Download

"対象をファイルに保存" でよろしく。 当然フリーウェアですよ。


Directory-Structure

comic/
 |-- Comic.js       // このスクリプト
 |+- comic-1/       // "comic-1" を為す一連のファイルがあるディレクトリ.
     |-- index.html // "comic-1" を表示するHTML. (HTMLソースは上のソースを参考にして記述)
     |-- 01.png     // "comic-1" を為す連続する画像. (桁と拡張子は全て統一する)
     |-- 02.png
     |-- 03.png
     ...
     |-- 27.png
 |+- comic-2/       // "comic-2" ディレクトリ. Comic.js は "comic-1" と共用で使う.
     |-- index.html
     |-- 001.jpg
     |-- 002.jpg
     |-- 003.jpg
     ...
     |-- 013.jpg
 ...

Comic.js を、上の設置例のように、HTMLよりひとつ上の階層に置くとき、 Comic.js を呼び出すソースは、
<script type="text/javascript" src="Comic.js"></script>
ではなく、
<script type="text/javascript" src="../Comic.js"></script>
とか書くのですよ。 (当たり前のことなのだけど一応。)


Sample-Source

<script type="text/javascript" src="Comic.js"></script>

<div id="comic" class="section">
    <h2>Comic</h2>
    <ul class="images">
        <li id="for-image2">
            <a rel="prev" href="#image" accesskey=",">
              <!--見開きのときに使う (任意) / last が無いときはこの要素の src から取得-->
                <img id="image2" src="http://glas-gather.org/comic/disorderly/27.jpg" alt="最後のページの画像" /></a>
        </li>
        <li id="for-image">
            <a rel="next" href="#image" accesskey=".">
              <!--画像 (必須) / 各設定のための要素が無いときはこの要素の src から取得-->
                <img id="image" src="http://glas-gather.org/comic/disorderly/01.jpg" alt="最初のページの画像" /></a>
        </li>
    </ul>
    <noscript>
      <!--JavaScriptが有効でない人のために、画像へのリンクを用意しておくと親切-->
        <ul>
            <li><a href="image/01.jpg">01P</a></li>
            <li><a href="image/02.jpg">02P</a></li>
            <li><a href="image/03.jpg">03P</a></li>
            <li><a href="image/04.jpg">04P</a></li>
            <li><a href="image/05.jpg">05P</a></li>
        </ul>
    </noscript>
</div>
<hr />
<form id="leader" class="section" action="#leader" method="get">
    <h2>Leader</h2>
    <fieldset class="interface">
        <legend>Interface</legend>
        <dl>
            <dt>現在のページ</dt>
            <dd>
                <label title="現在のページ">
                    <input type="text" name="page" value="1" class="page" accesskey="@" />
                </label>
                <label title="先読みしたページ">
                    /
                    <input type="text" name="preload" value="" class="page" accesskey="^" />
                </label>
                <label title="クッキーに現在のページ情報を保存する?">
                    <input type="checkbox" name="cookie" value=";" accesskey="?" />Cookie
                </label>
            </dd>
            <dt>前後移動</dt>
            <dd>
                <ul>
                    <li><button type="button" accesskey="{" onclick="Comic._.go(0)" onkeypress="this.onclick()" title="最初のページへ">first</button></li>
                    <li><button type="button" name="prev" accesskey="[" title="前のページへ戻る">prev</button></li>
                    <li><button type="button" name="next" accesskey="]" title="次のページへ進む">next</button></li>
                    <li><button type="button" accesskey="}" onclick="Comic._.go(-1)" onkeypress="this.onclick()" title="最後のページへ">last</button></li>
                </ul>
            </dd>
            <dt>拡大・縮小, 見開き</dt>
            <dd>
                <label title="画像の拡大・縮小" accesskey=":">
                    <select name="zoom">
                        <option value="25">25%</option>
                        <option value="50">50%</option>
                        <option value="75">75%</option>
                        <option value="100" selected="selected">100%</option>
                        <option value="125">125%</option>
                        <option value="150">150%</option>
                        <option value="175">175%</option>
                        <option value="200">200%</option>
                        <option value="250">250%</option>
                        <option value="300">300%</option>
                    </select>
                </label>
                <label title="1P表示 / 見開き表示" accesskey="/">
                    <select name="spread">
                        <option value="0" title="1ページずつ読む">One-Page</option>
                        <option value="1" title="奇数ページで見開き">Odd-Spread</option>
                        <option value="2" title="偶数ページで見開き">Even-Spread</option>
                        <option value="-1" title="全ページを羅列する">All-Pages</option>
                    </select>
                </label>
            </dd>
        </dl>
        <div class="hidden">
        <!--以下は設定 (任意) 無ければ image から自動取得-->
          <!--最初の画像ファイルの番号-->
            <!-- <input type="hidden" name="first" value="1" /> -->
          <!--最後の画像ファイルの番号-->
            <!-- <input type="hidden" name="last" value="13" /> -->
          <!--全画像ファイルの番号の共通の(最低)桁数-->
            <!-- <input type="hidden" name="digit" value="2" /> -->
          <!--全画像ファイルのある共通のディレクトリ-->
            <!-- <input type="hidden" name="dir" value="image/" /> -->
          <!--全画像ファイルの共通の拡張子-->
            <!-- <input type="hidden" name="extension" value="jpg" /> -->
          <!--画像を先読みするとき、その限界数-->
            <!-- <input type="hidden" name="prelimit" value="20" /> -->
          <!--画像が別フレームにある場合そのフレームのname値-->
            <!-- <input type="hidden" name="frame" value="image-page" /> -->
          <!--クッキーやURL情報から、公開している設定を変えられるようにする-->
            <!-- <input type="hidden" name="query" value="1" /> -->
          <!--キー・ジェスチャーを有効にする-->
            <input type="hidden" name="gesture" value="1" />
        </div>
    </fieldset>
</form>

Specs

以下、設定とか仕様とかのメモ。
上のHTMLのサンプルソースを見ながらどうぞ。

JavaScriptについて

ページ数とかの必要な設定は、HTML内の要素で行います。
JS内はいじんなくてよさげです。

JS内にも設定がありますが、 これは、設定のためのHTML内の要素を取得するための設定です。
もし要素名を変えたくなったときは、この設定を変更すればよいです。

設定のための要素は、 Form要素内にあれば name値 により指定できますし、 Form要素外であれば id値 で指定してやります。

JSは、一応オブジェクト指向的に書かれてるので、
new Comic({ 新しい設定 })
とやると、同じページで複数の漫画が動かせるでしょう。 (やるひとおらんだろうけど)

設定について

設定で必要なのは、上のソースで言えば、 <div class="hidden"> の中にある <input>族です。

設定は任意です。 各項目が未設定(空白や 0 の場合も含む)の場合は、
<img id="image">
の画像ファイル名を元に、各値が設定されます。

それでも設定値が取得できなかった場合、 first値 には 0 が、 last値が 999 が、 他の値には 0空文字 が入ります。 (実際に無い数値にしても特に閲覧には困らないみたいなので)

first
最初の画像ファイルの番号
last
最後の画像ファイルの番号
digit
全画像ファイルの番号の共通の(最低)桁数
dir
全画像ファイルのある共通のディレクトリ
extension
全画像ファイルの共通の拡張子

※例えば、http://hoge.com/001~100.jpg だったら、
first : 1,
last : 100,
digit : 3,
dir : http://hoge.com/,
extenstion : jpg,
って感じ。

汎用のための設定として、以下の項目もあります。

prelimit
画像を先読みするとき、その限界数
frame
画像が別フレームにある場合、そのフレームのname
cookie
クッキーに現在のページ情報を保存する?
query
クッキーやURL情報から、公開している設定を変えられるようにする
gesture
キー・ジェスチャーを有効にする

ユーザー・インターフェイスについて

<img id="image">

メインの画像要素。(必須) ページを変えると、ここのsrcが変わる。

  • 画像左クリックで 1P進む。
  • 画像右クリックで 1P戻る。
<img id="image2">

この画像要素があると、見開きページに対応できます。(任意)

  • 画像左クリックで 1P戻る。
  • 画像右クリックで 1P進む。

また、last が無いときは、 この要素から最後のページの番号を取得しようとします。
なので、HTMLソースには、最後のページを書いておけばいいかもしれません。

<form id="leader">

この要素内に、以下(↓から)の設定要素を書けば、 id="***" の部分が name="***" でも許される。

以下(↓から)は全て任意の項目です。

<* id="prev">

その要素を押したとき 1P 戻る。

<* id="next">

その要素を押したとき 1P 進む。

また、次の画像を先読みしてるとき、
この要素の class 名に "loading" が追加される。
先読みし終わると、その class は消える。

<* id="page">

この要素のテキスト値に、現在のページ数が表示される。
この要素の値を変えると、そのページに飛ぶ。

<* id="zoom">

この要素の値を元に、画像が拡大・縮小する。

<* id="spread">

この要素の値によって、 1Pずつ見たり、見開きにしたり、全てのページを一気に並べたり、 そんなことができるようになったりもする。 (画面が狭いと並ばなかったりもする)

<* id="preload">

この要素があると、 ページを先読みしたら、その先読みしたページをこの要素に代入。
この要素の値を変えると、そのページから先読みを始める。

<* id="cookie">

この要素があると、ウィンドウを閉じたときに、 最後に読んだページ(最初と最後のページ以外)の情報がクッキーに保存されます。
この要素の値は、クッキーの保存日数になります。

ちなみに、 <input type="checkbox" id="cookie"> とチェックボックスにした場合、 クッキーを保存するかどうかは、ユーザーが選択できるようになります。

<* id="gesture">

この要素の値が有効なら、画像にフォーカスが当たっているときに キー・ジェスチャー(キーボードの特定のキーによる操作) が有効になります。

くわしくは キー・ジェスチャー機能の項 をご覧ください。

メソッド・プロパティについて

Comic.objects[this.form.id] (フォーム内に限る)

そのフォームの設定を元にした Comic オブジェクト。

Comic.objects[フォームのid]

その id を持つフォームの設定を元にした Comic オブジェクト。

Comic._

デフォルトの Comic オブジェクトを差す。

例えば、
<* onclick="Comic.objects[ デフォルトのid ].go()"> の代わりに、
<* onclick="Comic._.go()"> と記述できるようになる。

go( ページ数 )

そのページに進む。

<* onclick="Comic._.go(10)">

また、go(ページ数)は、うまく修正されます。
ページ数が、最後の番号以上だったら、最後のページに。
ページ数が、最初の番号以下だったら、最初のページに。
ページ数が、マイナスだったら、最後のページから数えて行きます。

prev()

前のページに戻ります。

<* onclick="Comic._.prev()">

next()

次のページに進みます。

<* onclick="Comic._.next()">

focus()

画像にフォーカスを当てます。 フォーカスを当てると、キー・ジェスチャーが使えるので便利です。

<* onclick="Comic._.focus()">

change_zoom( 倍率 )

画像が拡大・縮小されます。 (倍率は % 単位)

<* onclick="Comic._.zoom(200)">

change_spread( タイプ )

見開きになったりならなかったりします。

<* onclick="Comic._.spread(1)">

タイプ == 0
1ページのみ表示
タイプ == 1
見開きで表示 (奇数ページごと)
タイプ == 2
見開きで表示 (偶数ページごと)
タイプ == -1
全ページを一気に並べて表示
save_cookie( クッキーの有効期限の日数 )

クッキーに、現在の情報を保存します。

<* onclick="Comic._.save_cookie(30)">

query が有効でないときは、現在のページ数のみ。
query が有効なときは、公開している設定要素の値を全て保存します。

preload( ページ数 )

そのページから、画像を先読みしていきます。

<* onclick="Comic._.preload(12)">

reinit()

今のフォーム内の要素の値を元に、 そのオブジェクトをリセット・再設定します。

キー・ジェスチャーについて

画像にフォーカスが当たっているとき、 キーボードの特定のキーを押すことで、いろいろイベントが起こせます。

画像にフォーカスを当てるには、 一度画像をクリックするか、 デフォルトでは accesskey.(ドット) を指定してるので、 Windows なら "Alt + ."、 Macintosh なら "Ctrl + ." を押すと良さげです。 (ブラウザによってはこの限りではありません)

← キー (左矢印)
前のページに戻ります。 (prev())
→ キー (右矢印)
次のページへ進みます。 (next())
Home キー
最初のページに戻ります。 (go(0))
End キー
最後のページに進みます。 (go(-1))
B キー (Back)
前のページに戻ります。 (prev())
N キー (Next)
次のページへ進みます。 (next())
F キー (First)
最初のページに戻ります。 (go(0))
L キー (Last)
最後のページに進みます。 (go(-1))
M キー (Minus)
画像を 5% 縮小。 (change_zoom( x - 5 ))
P キー (Plus)
画像を 5% 拡大 (change_zoom( x + 5 ))
テンキーの - キー (マイナス) (Opera以外)
画像を 5% 縮小。 (change_zoom( x - 5 ))
テンキーの + キー (プラス) (Opera以外)
画像を 5% 拡大。 (change_zoom( x + 5 ))

その他の仕様

他に?

要望とかあったらどぞー。


Q&A

HTMLの書き方がわかりません

サンプルソース をそのままコピーして、
メモ帳にそのまま全文ペーストして、
ファイル名を "test.html" にして保存して、
ブラウザで表示させればOKです。

わかんなかったらエライ人にきいてネ。

Webコミックを連載してるんだけど、 「〇ページ目更新」 というように更新ページを関連付けるには?

<a href="comic.html?13">13ページ目更新
ってやると 13P目 からスタートしますよ。 (このページ直接指定は、 query 設定値の有無によりません)

フレームのページのとき、URL情報から設定を指定するには?
frame.html     // 親フレームのHTML
 |- image.html // イメージがあるHTML
 |- tool.html  // Comic.js を呼び出す、ツールボタンなどがあるHTML

上記のような構造であるとして。
親フレームにURL情報があれば、親フレームのURL情報をチェックし、
親フレームにURL情報が無ければ、 Comic.js を呼び出したHTMLのURL情報をチェックします。

つまり、 http://~~/frame.htmlhttp://~~/tool.html?15 なら、15P
http://~~/frame.html?10http://~~/tool.html?15 なら、10P、 になります。

画像が image/hoge_0.jpg ~ image/hoge_100.jpg ってなってるんだけど、どう設定に書けばよい?
first (最初の画像)
0
last (最後の画像)
100
dir (ディレクトリ)
image/hoge_
digit (最低桁数)
1
extension (拡張子)
jpg

……で、いけるかと。

ひとつのHTMLで複数のコミックを表示させたいんだけど。

設定値を直接指定してやればいいのです。

手順を以下に簡単に書きます。

  1. "サンプル" の "サンプル (別の漫画)" のように、 必要な設定を公開する。 (ユーザーが入力・選択できるようなフォームタイプにする)

  2. query 設定値を有効にする。 (<input type="hidden" name="query" value="1" />)

  3. それから、その Comic-Leader.js を入れた HTML (例えば comic.html) へのリンクを、次のように書く。

    • <a href="comic.html?first=1&last=13&digit=2&extension=jpg&dir=comic1/">comic1</a>
    • <a href="comic.html?first=1&last=13&digit=2&extension=jpg&dir=comic2/">comic2</a>

いかがでしょうか。 (ただ、それでくれぐれも他所様のコミックを引っ張って来て貼ったりしないようにしましょうね。)

"必要な設定を公開する" 必要があることに注意してください。 公開するのはいいけど、ユーザーには見せたくないな、ってときは、 スタイルシートでそのアイテムを display:none; するなりして、対処してください。:-(

"拡大・縮小"とか"見開き"とか"クッキー"とかいらないんですけど

HTMLのソースから、その部分を削除すればいいじゃない。

"拡大・縮小"を、セレクトボックスじゃなくてテキストボックスにできる?

"拡大・縮小"に限らず、全ての設定要素は、割と何でもよさげです。

<select name="zoom"> でも
<input type="text" name="zoom"> でも
<input type="radio" name="zoom"> でも
<input type="checkbox" name="zoom"> でも
<textarea name="zoom"> でも、
言ってしまえば <a id="zoom"> でもいいのです。
まあ <a> だと内容の変更はできないのですけどね。:-P

"見開き"にしたけど見開かないのだが

サンプルソースそのままでは見開き(横に並ぶ)にはなりません。
サンプルでも、画面が小さいときは、横に並びません。

見開きモードにしたとき、 image2 の画像 には、 image の画像のひとつ前の画像が表示されます。
見開きモードでないときは、 image2 には display:none; が付加されます。

見開きにするには、いくつか方法があるので、以下に書きます。

  • スタイルシートの float を使ってどうにかこうにかする。 (サンプルはこの手法)
  • スタイルシートの display:inline;white-space:nowrap; を使ってどうこうする。
  • HTMLで、リストを使わずに、画像を単に並べる
  • HTMLで、<table>タグを使ってどうこうする。

サンプルソース では、 image2 の画像の位置が image の画像よりも先にある、 ということに注意してください。
これはこれでいいのですが、 ただ、日本の漫画が、右から左に読むのが一般的なことを考えると、 ちょっと困った事態になります。
image2 のが image よりも先なので、 並べると、左から右に読む、配置になってしまうのです。
かと言って、配置を逆にすると、今度は、 画面が小さくて、見開きが縦に並んでしまったときに、不自然になります。

サンプルでは、 スタイルシートが効かないときでも、画面が小さいときでも、 特に不自然にならないように、 今の順配置で float:right を使って対処していますが、 これは好きなようになさって構わないと思います。
どうしても見開きで見せたいのなら、 <table>タグを使えばいいのです。:-)

サンプルのソースのアクセスキーを教えて。

こんな質問来るわけないけど、まあこの場を借りて。

. (ドット)
image の画像の親の <A> に対応します。
キーボードの "." の上が ">" なのでこれに。
, (カンマ)
image2 の画像の親の <A> に対応します。
キーボードの "," の上が "<" なのでこれに。
@ (アットマーク)
page (現在のページ) のボックスに対応します。
いまどこ(何ページ)にいるか、というので "at" の意味で。
[ (左の角括弧)
prev (前のページに戻る) にボタンに対応します。
前と次、というような対になるキーとして、 左と右、という括弧のキーを選びました。
] (右の角括弧)
next (次のページに進む) のボタンに対応します。
{ (左の開き括弧)
go(0) (最初のページに戻る) のボタンに対応します。
Shift を押す必要があるキーは、 "Alt + Shift + [" というようにやればアクセスできるはず。
} (右の開き括弧)
go(-1) (最後のページに進む) のボタンに対応します。
: (コロン)
zoom (拡大・縮小) のボックスに対応します。
比較の "x 対 y" を "x : y" って書くことによりこのキーを選択。
/ (スラッシュ)
spread (1P表示 / 見開き表示) のボックスに対応します。
分割 → 割る → "x 割る y" → " x / y" って書くので。
; (セミコロン)
cookie (クッキーに保存?) のボックスに対応します。
クッキー → おいしそう → よだれがでる → ";"
……ごめん、超こじつけ。
画像を先読みすると重くなる?

例えば画像のサイズを 250kb とした場合、一気に200ページ読み込むと、 最低 50000kb = 約50Mb をキャッシュしてしまい、重くなりそうですね。

11/22 の更新で prelimit の設定項目を増やしました。 この値を調節してみてください。

例えば、prelimit を 20 にすると、 今表示されているページから数えて、20ページ先までしか先読みしなくなり、 また、20ページ前までのページはクリアされます。 つまり、前後20ページ、合計40ページまでキャッシュされることになります。

それと、prelimit がない、または、値を 0 にすると、 自動でデフォルト値の 20 が設定されます。 負の値 (-1等) にすると先読みしなくなります。

著作権を放棄するわけじゃないけど、表示はおまかせ。 邪魔ならつけなくても一向に構わないよ。

リンクとかも、自分が喜ぶだけで、特に貼る義務もないです。 改造とかもお好きにどうぞ。