IIIF対応ビューワ:最近の話題

IIIFは、おかげさまで徐々に国内にも広がってきておりまして、あちこちの画像をまとめて統合的に活用することも現実的なものとなってきました。一方、対応ビューワの方にも少し新しい話が出てきております。やはり注目はMirador3で、これまでの課題を解決しつつ、よりさくさくと動くように、使い方を分かりやすく、そして、より拡張性の高いものを目指して開発が進みつつあります。最近ようやく、開発版が割と簡単に使えるようになりましたので、ちょっと画像が粗くて恐縮ですが、とりあえず以下の動画でちょっとお届けします。

youtu.be

インターフェイスの日本語化も現時点では一応できています。まだ、アノテーションなどいくつかの機能が完成してないようで、 jsファイルも16MBほどあるのでこれからブラッシュアップしていくものと思われますが、デザインだけを見ても今までのバージョンとは かなり雰囲気が違っています。ソースコードはこちらから取得できますので、よかったらお試ししてみてください。 https://github.com/ProjectMirador/mirador/

もう一つ、TIFYというものがゲッティンゲン大学にて開発されているようです。こちらはモバイルにも対応しているとのことですが、後発な分、先行ビューワの微妙に不便だったところがケアされているような感じで、難しいことをいわなければ全体的に使いやすい感じがします。

f:id:digitalnagasaki:20190511173528p:plain

アノテーションも、Fulltextタブをクリックすると内容は表示されるようです。TIFYについては、まだ検証が不十分なので、もう少し調べてみようと思っております。

簡単なIIIFビューワを作ってみよう(6): もう少し便利なインターフェイスを

透過度や位置を変更できるようにしましたが、いちいち数字を入れてボタンを押す・・・という操作はいかにも面倒です。透過度の調整は、スライダが適しているように思えます。そこで jQuery UIのスライダを組み込んでみましょう。

とりあえず、動くスライダを表示してみる

jQuery UIは、jQueryで便利なインターフェイスを提供してくれるライブラリのようなものです。うまく組み込むことができれば、とても便利に使うことができます。基本的には、ダウンロードしてscriptタグで読み込まれば準備は完了です。

ダウンロードはこちらからです。以下のページ画面の右側の方にある「stable」をクリックしてください。 f:id:digitalnagasaki:20190504213317p:plain

ダウンロードしたら、展開してください。そうすると、たとえばダウンロードしたものが jquery-ui-1.12.1.zip であれば、 jquery-ui-1.12.1 というフォルダ(ディレクトリ)ができているはずです。jquery-uiはディレクトリ構成をいじるとややこしいことが起きるかもしれませんのでこのまま使いましょう。

まず、とにかくスライダを表示させることを目標にしてみます。jquery-uiでスライダを表示できるようにするには、jquery-uiのcssファイルとjsファイルをページに読み込ませる必要があります。

<title>私の簡易IIIFビューワ</title>
    <link rel="stylesheet" href="jquery-ui-1.12.1/jquery-ui.min.css">
    <!-- 上記のタグを追加してcssファイルを読み込めるようにします。-->
    <style>
    <script src="jquery-3.4.1.min.js"></script>
    <script src="jquery-ui-1.12.1/jquery-ui.min.js"></script>
    <!-- 上記のタグを追加してjsファイルを読み込めるようにします。-->
    <script src="openseadragon-bin-2.4.0/openseadragon.min.js"></script>

以上のようにして、cssファイルとjsファイルを読み込めるようにしたら、スライダを表示するエレメントをどこかに追加してみましょう。とりあえずビューワ画面の直上がいいような気がしますので、以下のようにしてみます。

    <div id="slider"></div>
    <!-- 上のタグを追加します。-->
    <div id="myViewer" class="openseadragon" style="width:600px;height:600px"></div>

そして、スライダを表示するjavascriptを書きます。

    <script>
  $(function(){
    $( "#slider" ).slider();
    // 上の一行を、最初の方に追加します。

そうすると、単にスライダが追加され、動かせるようになっているはずです。 今回のサンプルはこちらです。

スライダを重ねた画像の透過度と連動させてみる

スライダは色々な設定を加えることができます。透過度はcssのopacityで設定できますので、 以下のようにスライダのjavascriptに追記して、スライダの値とopacityが連動するようにしてみます。

    $( "#slider" ).slider({
      min: 0,
      //最小値
      max: 100,
      //最大値
      value: 100,
      // 最初の値
      slide: function( event, ui ) {
         var opa = ui.value / 100;
         // ui.valueで、スライダの値をとれます。opacityは1が最大値なので、スライダの値(最大値100)を100で割った値を用います。
         console.log();
        $(".overLayImg").css({'opacity':opa});
        //重ねた画像のクラスを指定して、cssでopacityの値を与えます。
      }
    });

ついでに、幅が広すぎると使いにくいので、スタイルを設定してスライダの幅を少し狭くしてみます。

<div id="slider" style="width:50%"></div>

今回のサンプルはこちらです。

簡単なIIIFビューワを作ってみよう:まとめ

IIIF Presesntation APIを理解する上で、IIIF ビューワを作ってみるとよいのではないかと思いまして、ちょっとチュートリアル的なものを作ってみました。

と言っても、一から作るわけではなく、画像表示部分はOpenSeadragonにおまかせ、という話です。OpenSeadragonが担当してくれるところは、ほぼIIIF Image APIと重なるので、そこはまた別の機会にということで、今回は、OpenSeadragonを核にしてIIIF Presentation APIを活用して閲覧システムを作ろう、という話です。

基本的に、作成に際してはサーバは不要で、ローカルで動かすシステムです。ただ、外部のIIIF Manifestファイルを読み込むという話ですので、ネットにつながっている必要はあります。

以下、順番に解説を読みながら取り組んでいただくと、IIIF Presentation APIについて少し理解が深まると思います。また、途中からは、それを離れておまけの機能作成に行ってしまっておりますが、さらに利便性を高めるための基礎になるようなものをいくつか採り上げておりますので、こういったものを踏まえてさらにうまく活用していただいたり、よりよいサービスを展開したりしていただけますと幸甚に存じます。

簡単なIIIFビューワを作ってみよう(1): IIIF Presentation APIの理解に向けて

簡単なIIIFビューワを作ってみよう(2): IIIF Presentation APIの理解に向けて

簡単なIIIFビューワを作ってみよう(3): おまけの機能を少し

簡単なIIIFビューワを作ってみよう(4): 画像切り出しをしてみよう

簡単なIIIFビューワを作ってみよう(5): 切り出した画像を重ねてみる

簡単なIIIFビューワを作ってみよう(6): もう少し便利なインターフェイスを

簡単なIIIFビューワを作ってみよう(5): 切り出した画像を重ねてみる

切り出しができたところで、さてこの後はどうしましょうか、ということになりますが、OpenSeadragonには図形や画像を重ねて一緒にズームできるようにするAPIが用意されていますので、切り出した画像を重ねてみる、という仕組みを用意してみましょう。これはこちらで紹介したものに使われている機能の基本的な部分です。

まずは切り出し画像を重ねてみる

今回は、「この画像を重ねる」という操作をボタン押し下げでできるようにする、ということで、以下のようにして、 画像を切り出した際にボタンが表示されるようにしてみます。ここでは、後の処理を簡単に書けるようにするために、 ボタン要素に属性 data-i を渡して最大サイズの切り出し画像のImage API URLを付与しておきます。

        $("#imgDiaC1").html('<img src="'+pct+'" alt="A part of the image">');
        $("#imgDiaC3").html('<button id="putImg" data-i="'+pctf+'">この画像を重ねる</button>');
        // $("#imgDiaC3").text(''); という行を上記の行で上書きします。
        $("#imgDiaC3").append('<br><a href="'+pct+'">画像部分URL (IIIF対応)</a>');
        $("#imgDiaC3").append('<br><a href="'+pctf+'">画像部分URLフルサイズ (IIIF対応)</a>');

その後、「このボタンを押すと切り出し画像を重ねる」という操作を追加します。以下のように書いてみています。やや 複雑な感じになっているのは、OpenSeadragonの仕様により、画像の縮尺や縦横幅等をそのままにして表示するためには 画像のサイズを画像幅に対する相対値で示さなければならないためです。

以下のプログラムでやっていることをおおまかに説明すると、id: putImgの要素がクリックされた時に、一連の処理を始めます。 まず最初に、imgタグを作成してimgEltに代入します。これはとりあえずこのまま置いておいて、次に 画像の最大の横幅を取得してから、切り出し画像のImage APIのURLを取得してその中に含まれる切り出し箇所の座標情報を 取り出します。そして、画像全体の横幅に対する切り出し画像の縦横幅の相対値を取得します。その後、imgタグが代入 されているimgEltに対して、srcで表示対象となる切り出し画像のImage API URLを指定し、クラス名とidを与えて、 viewer.addOverlay({ ... })で全体画像に重ねます。重ねる際の位置情報としては、x, y 座標は決め打ちで、縦横幅は今回取得した相対値を 渡します。

以下、もう少し詳しく解説しておきます。

   $("body").on("click","#putImg",function(){
          // id: putImgのエレメントをクリックしたらこの処理を始めます。 
      var imgElt = document.createElement("img");
          // imgタグ(エレメント)を作成して変数imgEltに入れておきます。
      var imgUrl = $(this).attr("data-i");
          // id: putImgに付与していた属性data-i の値(Image APIのURL)をimgUrlに代入します。
          var rectw = viewer.world.getItemAt(0).source.width;
          // 現在の画像のフルサイズの横幅を取得して変数rectwに入れておきます。
      var arUrlParam = imgUrl.split(/\//);
          // imgUrlに入っているImage APIの URLを / で分割して配列にして、arUrlParamに入れておきます。
      var paramPos = arUrlParam.length -4;
          // arUrlParamのうち、切り出し座標が入っている箇所を取り出します。後ろから4つ目なので、
          // 要素の個数を .lengthで数えた上で、4を引くことで前からの位置を取り出す。
      var arPct = arUrlParam[paramPos].split(/,/);
          // 座標位置情報を , で分割してx, y座標と縦横幅を取り出せるようにしておきます。
      var sqw = arPct[2] / rectw;
      var sqh = arPct[3] / rectw;
          // 縦横幅を取り出して、それぞれ最大横幅に対する相対値を取得して変数にいれいます。
      imgElt.src = imgUrl;
          // imgEltの属性srcに対して変数 imgUrl、つまり切り出し画像のImage APIのURLを代入します。
      imgElt.className = "overLayImg";
           // あとで操作するためにクラス名としてoverLayImgをつけておきます。
      imgElt.id = "overLayImg";
          // あとで操作するためにidとしてoverLayImgをつけておきます。
      viewer.addOverlay({
          // viewerのインスタンスに対してoverlayを追加します。
         element: imgElt,
                 // 追加するエレメント imgElt を指定します。
         location: new OpenSeadragon.Rect(0.2, 0.2, sqw,sqh)
                  // 追加するimgEltの位置情報を矩形で渡します。ここでは相対値を渡す必要がありますので
                  // 上で作成した縦横幅を指定しています。x, y座標はとりあえず固定値です。
          });                 
       });

これで、切り出した画像を画像全体に重ねることができるはずですが、いかがでしょうか。 今回のサンプルはこちらです。

重ねた切り出し画像を動かしたり透過したりしてみる

ただ重ねただけだとまだまだ足りない感じがします。やはり重ねたものは位置合わせをしたり透かしてみたりしたいですね。 とりあえずは基本的な機能の確認ということで、数値を入力することで位置を動かしたり透過したりできるようにしてみましょう。

まずは数値入力欄を作ってみましょう。以下のように、それぞれidを与えて値を取り出せるようにしておいて、値はデフォルト値 としてそれぞれ1.0, 0.2, 0.2を入れておいて、ボタンも用意しておきます。ボタンのidはputParamとしておきましょう。

    透過度:<input type="text" size="4" id="opa" value="1.0">, 
    横位置:<input type="text" size="4" id="prx" value="0.2">,
    縦位置:<input type="text" size="4" id="pry" value="0.2">
    <button id="putParam">設定</button>

ここからが本番です。id: putParamの要素をクリックしたら、各値を読み込んで、それに基づいて重ねた切り出し画像の透過度を変更したり位置を移動したりします。 これは、前回の「画像を重ねる」とかなり近いプログラムですが、少し異なる部分がありますので、異なる部分について解説をしておきます。

   $("#putParam").click(function(){
        // id: putParam をクリックすると以下の処理を行います。
        // このエレメントは最初から用意されていますのでこのように指定できます。
      var opa = $("#opa").val();
      var prx = parseFloat($("#prx").val());
      var pry = parseFloat($("#pry").val());
          // 上記でそれぞれのinputの値を取得して各変数に入れます。
      $(".overLayImg").css({'opacity':opa});
           // 変数opaに入っている数値を透過度として設定します
      var imgUrl = $("#putImg").attr("data-i");
         var rectw = viewer.world.getItemAt(0).source.width;
      var arUrlParam = imgUrl.split(/\//);
      var paramPos = arUrlParam.length -4;
      var arPct = arUrlParam[paramPos].split(/,/);
      var sqw = arPct[2] / rectw;
      var sqh = arPct[3] / rectw;
      var overlay = viewer.getOverlayById("overLayImg");
          // 変数overlay に、先ほど作成したid: overLayImgエレメントを代入します。
      r = new OpenSeadragon.Rect(prx,pry,sqw,sqh);
           // 変数prx, pry中の位置情報を渡して rというオブジェクトを作成してrに代入します。
      overlay.update(r);
           overlay.drawHTML(overLayImg.parentNode, viewer.viewport);
           // overlayをアップデートして再描画。
    });

ということで、重ねた切り出し画像を動かしたり透過させたりできるようになりました。 今回のサンプルはこちらです。

ここまで、色々な機能の基本的な使い方を押さえてきました。それぞれ様々に 応用できますので、これらをベースに応用の仕方を色々と考えてみていただければと思っております。

一方、ここまで、見た目についてあまり気にせずに突き進んできました。styleを調整してみたり、 不要な時は表示されないようにするなど、見た目を調整する方法は色々ありますので、 そろそろちょっと工夫してみていただくとよいかもしれません。

それから、切り出し画像の位置を移動させるのに、いちいち数値を入れるのはなかなか面倒な時が多いです。そのような場合に、たとえばスライダーを入れてみたり、 あるいは直接切り出し画像をドラッグできるようにしたりと、方法としては色々あると思います。スライダーについては筆者も実装してみたので またそのうち実装の仕方を書ければと思っております。

ということで、今回はとりあえずここまでとしたいと思います。お疲れ様でした。

簡単なIIIFビューワを作ってみよう(4): 画像切り出しをしてみよう

前回までで、ページめくりからページ指定までできるようになりました。ここまできたら、もう少し色々な機能をつけてみたくなります。そこで、IIIFの面白さの一つとしてよく採り上げられる、画像切り出しをやってみましょう。

画像切り出しプラグインの導入

切り出しをするには、OpenSeadragonのプラグイン、selection.jsを使うと便利です。このプラグインは、切り出し領域を人が手作業で指定するための便利なインターフェイスと、切り出し対象の座標情報を返戻する機能を提供してくれます。

このプラグインでは、javascriptのファイルであるselection.jsとともに、アイコン等の画像も提供しています。ですので、アイコン画像もダウンロードして適切なフォルダ(ディレクトリ)に置いておく必要があります。それを踏まえた上で、ダウンロードしてみましょう。ちなみに、色々検討してみましたが、今のところ一番やりやすそうなのは、githubのページから、zipファイルをダウンロードして、zipファイルを展開してから、必要なファイルを適切なフォルダ(ディレクトリ)にコピーするという方法です。  このzipファイルをダウンロードして展開すると openseadragonselection-master というフォルダ(ディレクトリ)ができます。この中にdistというフォルダ(ディレクトリ)があり、その中に openseadragonselection.js というファイルがあります。このファイルを jquery-3...min.jsと同じ階層にコピーしましょう。さらに、openseadragonselection-master というフォルダ(ディレクトリ)の中にある images というフォルダの中にある png画像をすべてコピーして、openseadragon-bin-2.4.0 の中のimages の中に(=他のOpenSeadragonアイコン画像と同じフォルダ(ディレクトリ)に)コピーしておきましょう。

これでダウンロードとファイルの設置は完了しました。次に、とりあえず selection.jsプラグインを読み込ませてみましょう。 まずは、head要素の中で、openseadragon.min.jsの次にこのプラグインを読み込ませるタグを追加します。

    <script src="openseadragon-bin-2.4.0/openseadragon.min.js"></script>
    <script src="openseadragonselection.js"></script>

次に、script要素の一番最後に以下のように selection()を書き込みます。selectionプラグインを読み込んだことで、viewerインスタンスにselectionを使わせることができるようになりました。

   var selection = viewer.selection();
  });
    </script>

これを保存してからGoogle Chromeで開いてみると、以下のように、selectionボタンがビューワ部分に登場し、それをクリックすると画面上で選択操作ができるようになります。 f:id:digitalnagasaki:20190504143616p:plain

ただし、このままですと、selectionしたあとにどうするかということを何も定義していないので、切り出しをしても、その後に何も起きません。切り出した後に何かさせたければ、selectionに少し命令を追加する必要があります。

今回のサンプルはこちらです。

なお、OpenSeadragonには色々なプラグインが提供されています。 公式サイトにリストがあり、多くのものはデモも提供していますので、ご覧になってみて、色々アイデアをふくらませてみるのも面白いかもしれません。

選択した領域の座標情報を取得・表示

画像切り出しをするためには、切り出したい領域の座標情報が必要です。selection.jsプラグインはこれを簡単に取得させてくれますが、とりあえず、この動作のみを確認してみましょう。

    <div id="myViewer" class="openseadragon" style="width:600px;height:600px"></div>
座標情報: <span id="coordx"></span>, <span id="coordy"></span>, <span id="coordw"></span>, <span id="coordh"></span>
    <script>

上記では座標情報を書き込むための要素を用意しておきます。それぞれのspan要素にcoordx, coordy, coordw, coordhのidを付与しておきます。

これらのidに対して、以下のようにして onSelection の値をrectに入れて、それをそれぞれ rect.x, rect.y, rect.width, rect.heightで取り出して書き込みます。

var selection = viewer.selection({
      onSelection: function(rect) {
        $("#coordx").text(rect.x);
        $("#coordy").text(rect.y);
        $("#coordw").text(rect.width);
        $("#coordh").text(rect.height);
      }
});

これで、selection.jsで選択した画像の領域の座標情報が表示されます。この座標の場合は画像上のピクセル情報です。

今回のサンプルはこちらです。

選択した領域を切り出して表示させる

さて、いよいよ切り出して表示をしてみます。切り出した部分の画像上での座標情報が取得できれば、あとはそれをIIIF Image APIに適用することで切り出し画像を表示したり共有したりできます。

今回は、小さな画像を表示させつつフルサイズ画像へのリンクも作成してみたいと思います。わかりやすくするために、書き込む場所を二つ用意します。

    座標情報: <span id="coordx"></span>, <span id="coordy"></span>, <span id="coordw"></span>, <span id="coordh"></span>
    <div id="imgDiaC1"></div>
    <div id="imgDiaC3"></div>
    <script>

つぎに、切り出し座標を基にしてIIIF Image APIのURLを作成します。

カラーの画像をJpeg形式で同じカラーで入手しようとするなら、IIIF Image APIのURLの基本的な構造は以下のようになります。

http://(IIIF Image APIの基本URL)/(切り出し座標)/(画像の表示サイズ)/(画像の回転度)/default.jpg

「IIIF Image APIの基本URL」というのは、IIIF Manifestに含まれるものであり、言い方を換えると、info.jsonを含むURLからinfo.jsonというファイル名を削除したものであるとも言えます。 以前に書いた以下のものを思い出してみてください。

maniJson["sequences"][0]["canvases"][0]["images"][0]["resource"]["service"]["@id"]

「切り出し座標」のところには今回取得した座標情報を記述します。もし切り出しをまったくしない場合には「full」と書いておくことになっています。

「画像の表示サイズ」は表示したい縦横サイズをここに記述します。最大サイズがよいという場合は「full」と書いておくことになっています。

「画像の回転度」は90度右回転であれば90、90度左回転であれば270、と書いておきます。回転させない場合には「0」です。

以上を踏まえつつ、IIIF Image APIのURLを以下のようにして作成してみます。

まずは簡単に概要を説明すると、まずは座標情報をそれぞれ変数に入れてから、前回の座標情報表示用の要素に表示をさせて、 その後に、Image API のURLの画像情報部分を作成し、その後、現在見ているページの画像の info.json のURLをviewerから取得して 末尾のinfo.jsonを削除してから画像情報部分と連結し、最後は二つの要素上でそれぞれ表示させます。

onSelection: function(rect) {
    var rectx = rect.x
    var recty = rect.y
    var rectw = rect.width
    var recth = rect.height
        // 後で扱いやすいように、とりあえず座標情報をそれぞれ変数に入れておきます。
        // これは好みの問題で、変数にいれずにそれぞれ直接以下で使うこともできます。
    $("#coordx").text(rectx);
    $("#coordy").text(recty);
    $("#coordw").text(rectw);
    $("#coordh").text(recth);
        // それぞれの座標表示要素にて座標情報を表示させます。
        var pct = '/'+rectx+','+recty+','+rectw+','+recth+'/200,/0/default.jpg' ;
        var pctf = '/'+rectx+','+recty+','+rectw+','+recth+'/full/0/default.jpg' ;
        // Image APIのURLの画像表示部分を作成します。
        // 表示画像の幅が200のものとフルサイズのものを用意します。
        var currentPage = viewer.currentPage();
         // 現在見ている画像が何枚目かを確認してその値を 変数currentPageに入れます。
        var currentiJsonUri = viewer.tileSources[currentPage].replace(/\/info.json$/,'');
        // viewer.tileSourcesには、現在の資料の画像のinfo.json URLのリストが配列
        // として入っています。currentPageで現在見ている画像のinfo.json URLを
        // 取得した上で、末尾のinfo.jsonを削除しています。その結果は 変数currentiJsonUri
        // に代入します。
        pctf = currentiJsonUri + pctf;
        pct = currentiJsonUri + pct;
        // それぞれの画像表示部分 pct, pctf を画像の基本URLが入っている currentiJsonUri と文字列連結します。
        $("#imgDiaC1").html('<img src="'+pct+'" alt="A part of the image">');
        // 上で作成した切り出し画像のURL(変数pctに入っている)をimgタグに組み込んで id: imgDiaC1 に表示させます。
        // そうすると切り出し画像がWebブラウザ上に表示されます。
        $("#imgDiaC3").text('');
        // こちらは、いったんid: imgDiaC3の内容を空にしてから、
        $("#imgDiaC3").append('<br><a href="'+pct+'">画像部分URL (IIIF対応)</a>');
        $("#imgDiaC3").append('<br><a href="'+pctf+'">画像部分URLフルサイズ (IIIF対応)</a>');
         // 二つのタグを作って追加 (.append)します。これらのタグは、それぞれ切り出し画像のURL
         // にリンクを張っています。
 }

いかがでしょうか。今回のサンプルはこちらです。

簡単なIIIFビューワを作ってみよう(3): おまけの機能を少し

前回までで、とりあえず、IIIF manifestを指定するとそこに含まれる画像を順番に表示して拡大縮小もできるようになりました。ここまでで、IIIFビューワのごく基本的な機能は作れたと言ってよいのではないかと思います。

ここからは、もう少し便利にするための小技をいくつか試してみましょう。

ページ番号をリストして直接アクセスできるように

いちいちページをめくっていくと、ページ数が増えてきたときにちょっと不便です。そこで、ページ番号をリストして、クリックするとそのページに飛べるようにしてみましょう。

そうすると、必要になるのは

  1. Manifestからのページ番号の取り出し

  2. 取り出したページ番号のリスト化

  3. リスト化したページ番号の表示

  4. ページ番号をクリックするとその番号を呼び出せるように

  5. 呼び出したページ番号のページをOpenSeadragonで表示

  6. クリックされるべきページ番号に色をつけたりカーソルをあわせると色が変わったりさせる

といったところでしょうか。これらを一通り書いてみましょう。

まず、Manifestからのページ番号の(1)取り出しと(2)リスト化です。 前回のスクリプトにてcanvasごとに処理していた箇所で、その番号を タグ化して変数に格納します。

 var pageNumbers = '';
 // 変数 pageNumbers を初期化する
      for(var e=0;e<maniJson["sequences"].length;e++){
         for(var ec=0; ec<maniJson["sequences"][e]["canvases"].length;ec++){
           var ece =  maniJson["sequences"][e]["canvases"][ec];
           var iJsonUri = ece["images"][0]["resource"]["service"]["@id"]+'/info.json';
           arIJsonUri.push(iJsonUri);
           pageNumbers += '<span class="pNum">'+ec+'</span>';
// canvasを一つずつ処理する際に、その番号をページ番号としてタグ化して
// 変数 pageNumbers に追記してリスト化

次に、リスト化したページ番号を(3)表示させましょう。まず、リスト化したページ番号を表示する場所(要素/エレメント)を作ります。

<div id="pageNum"></div>
<!-- OpenSeadragonビューワの直上にエレメントを作っておきましょう。idはpageNumとしておきます。-->
<div id="myViewer" class="openseadragon" style="width:600px;height:600px"></div>

そして、id: pageNumのエレメントに変数 pageNumbersを表示させます。

       viewer.open(arIJsonUri);
       $("#pageNum").html(pageNumbers);
           // viewer.open()の次の行で、id:pageNumに対してpageNumbersをhtmlとして表示させます。

ここまでで、ページ番号リストは表示できるようになったはずです。 次に、このリストで(4)個別のページ番号をクリックするとその番号を呼び出せるように した上で、(5)呼び出したページ番号のcanvas上の画像をOpenSeadragonに表示させます。

$(function(){
    // この行の次に以下の処理を追記します。
    $("body").on("click", ".pNum", function(){
   // 最初から用意されたタグではなく後からJavascriptで追記したものを処理する場合
   // .on() を使います。ここでは、body要素中に用意されたクラスpNum ( .pNum ) を
   // click した場合、function(){ ... } の中を実行することになります。
      var pNum = parseInt($(this).text());
      // クリックした要素におけるテクストを取り出し( $(this).text() )て、
      // 数値として扱えるように( parseInt( ... ) )して、変数 pNumに入れます。
      viewer.goToPage(pNum);
       // OpenSeadragonのインスタンスviewerに pNumページの画像を表示する
       // ように( .goToPage(pNum) )指示します。
    });
    // $("body").on("click", ".pNum", function(){の処理を閉じています。

これで、IIIF Manifestを読み込ませるとページ番号をリストして、 いずれかのページ番号をクリックするとそのページの画像が表示されるようになります。 ただ、これだけでは、ページ番号をクリックすると何かが起きるということをユーザに示すことができていません。 一般に、テキストが青色で下線がついていたり、カーソルをテキストにあわせるとカーソルの形状が変わったり、 テキストの色が変わったりすると、クリックした時に何かが起きるとユーザに理解させやすくなります。 そこで、クラス.pNumの要素に上記のようなスタイルを割り当てるべく、head要素中にstyle要素を設定します。

    <title>私の簡易IIIFビューワ</title>
    <!-- titleタグの次あたりに以下のものを追記します。-->
    <style>
     .pNum{color:blue;cursor:pointer}
     .pNum:hover{color:red}
    </style>

これで、ページ番号をクリックする意味があるとユーザに伝えやすくなるはずです。

今回のサンプルはこちらです。

ページ番号を1から始める

前回作ったものは、機能としては十分なのですが、ページ番号が0から始まっていて、ちょっとわかりにくいです。そこで、 ページ番号を1から始まるようにしてみましょう。

やり方としてはいくつかありますが、とりあえずここでは、HTMLにおける属性をjavascriptで処理するという方法を学ぶべく、以下のような改良をしてみます。

  1. 表示用のページ番号を作って呼び出し用ページ番号の要素に属性として与える

  2. リストされたページ番号をクリックすると属性値の呼び出し用ページ番号を呼び出してOpenSeadragonに読み込ませる

ということで、やってみましょう。まずは、以下のように、変数pecを作って表示用に1を足した数値を代入し、それを 表示用数値とする一方で、本来の呼び出し用ページ番号が入っているecの方は属性値としてクラスpNumの要素の属性data-nに与えます。

          var pec = ec+1;
           pageNumbers += '<span class="pNum" data-n="'+ec+'">'+pec+'</span>';

(上記では、 var pec = ec+1;を追記するとともに、pageNumbers += ...のところを書き換えています。)

次に、リストされたページ番号をクリックするとその属性値を呼び出してOpenSeadragonに読み込ませるようにするには以下のようにしてみます。

    $("body").on("click", ".pNum", function(){
      var pNum = parseInt($(this).attr("data-n"));
      // 属性data-nの値を取り出して($(this).attr("data-n"))、
      // 数値として扱えるようにして( parseInt(...))から変数pNumに入れます。
      viewer.goToPage(pNum);
     //ここは前回と同じです。

これで、ここでの目標は達成できるはずです。今回のサンプルはこちらです。

簡単なIIIFビューワを作ってみよう(2): IIIF Presentation APIの理解に向けて

さて、前回の続きです。

IIIFでの画像のURLをManifestから取り出す

先に見てきたように、画像の @id のJSONでの階層を確認しました。そこで、それを取り出して表示させてみましょう。$.ajaxで取得してmaniJsonに入れたmaniefstファイルで、「複数のsequenceの1つ目の複数のcanvasの一つ目の複数のimageの一つ目の下のresourceの下のserviceの下の@id」というのを取り出して、id: linkImageに表示させてみます。そこで、

     $.ajax({
        url:pUrl,
        dataType:'json'}).done(function(maniJson){
          $("#linkAttr").text('').text(maniJson["attribution"]);
          $("#linkLabel").text('').text(maniJson["label"]); 
          $("#linkImage").text(maniJson["sequences"][0]["canvases"][0]["images"][0]["resource"]["service"]["@id"]);
      });

以下、HTML部分で追加したもの

タイトル: <div id="linkLabel"></div>
帰属: <div id="linkAttr"></div>
Image URI のベース : <div id="linkImage"></div>

そうすると、たとえば https://gallica.bnf.fr/iiif/ark:/12148/btv1b10526547d/manifest.json おそらく、以下のように Image URIのベースのURLが表示されるはずです。

--

タイトル:

BnF, département Estampes et photographie, BOITE FOL-DE-10

帰属:

Bibliothèque nationale de France

Image URI のベース URL:

https://gallica.bnf.fr/iiif/ark:/12148/btv1b10526547d/f1

--

サンプルはこちらに置いておきます。

OpenSeadragonに画像を読み込ませる

ここまで来たら、次はいよいよ、info.jsonのURLをOpenSeadragonに読み込ませてみましょう。

以下のものをそれぞれ追記してください。

    <script src="jquery-3.4.1.min.js"></script>
    <script src="openseadragon-bin-2.4.0/openseadragon.min.js"></script>  
  </head>

上記ではまず、OpenSeadragon のjavascriptファイルを読み込みます。

    <!--https://gallica.bnf.fr/iiif/ark:/12148/btv1b10526547d/manifest.json-->
    <div id="myViewer" class="openseadragon" style="width:600px;height:600px"></div>
    <script>

上記では、OpenSeadragonのviewerを作成した際に表示させる場所をdivで指定します。viewerの画面サイズもとりあえずここで style="width:600px;height:600px" という風に指定します。

             arIJsonUri = [];
          const iJonUri = maniJson["sequences"][0]["canvases"][0]["images"][0]["resource"]["service"]["@id"]+'/info.json';
              $("#linkImage").text(iJsonUri);
          arIJsonUri.push(iJsonUri);
          viewer.open(arIJsonUri);
      });

Javascriptのところでは、前のスクリプトで#linkImageに読み込ませていたところに、info.json というファイル名をつけておきましょう。これはOpenSeadragonに読み込ませるために必要になるものです。さらにそれを、arIJsonUriという配列変数を作って( arIJsonUri = []; )、その変数に配列の値として代入しましょう( arIJsonUri.push(iJsonUri); )。そして、その配列変数を読み込ませる形で viewer.openをしてみます。ここでの「viewer」は、次に設定します。

    });
    var viewer = OpenSeadragon({
    id: "myViewer",
    prefixUrl:     "openseadragon-bin-2.4.0/images/",
    visibilityRatio:    1,
    minZoomLevel:       0.3,
    defaultZoomLevel:   0.7,
    sequenceMode:  true,
      initialPage: 0,
      tileSources:   [  ]
    });
  });
    </script>

ここでは、OpenSeadragonのviewerのインスタンスを一つ作成して、それを変数viewerに入れています。これで、このプログラム(を含むWebページ)では、特に工夫しない限り、変数 viewer を用いることでこのOpenSeadragonのインスタンスを操作できることになります。OpenSedragon({ ... }) の括弧内に書かれているのは、このインスタンスの初期設定です。まず、myViewerというidを持つ要素のところに表示するという設定があります。これは、試した限りではdiv要素でないとうまく動作しないようです。prefixUrlはOpenSedragon用のアイコン画像等が置かれているディレクトリを設定します。たとえば、別のディレクトリにカスタマイズアイコンを置いてそれをprefixUrlの値として指定すれば、カスタマイズアイコンが表示されることになります。その他、zoomサイズの設定など色々あります。IIIF viewerのように連続する画像を表示させたい場合には、sequenceModeをtrueに設定した上で tileSourcesの値として配列を与えるといいようです。(ですので、上記の arIJsonUri では配列変数になっています)。また、最初に表示するページとして「0(=1ページ目)」を指定しています。

サンプルはこちらです。

複数ページ(画像URL)を取り出してOpenSeadragonに渡してページめくり

さらに、複数ページを読み込めるようにしてみます。

先ほどの、画像のURLを取り出して /info.jsonを付記したところを、複数のcanvasを前提としてfor文で繰り返し、取得できたURLをすべて配列変数に入れて(arIJsonUri.push(iJsonUri);)、その配列変数をビューワのインスタンスに読み込ませます。(viewer.open(arIJsonUri); )

          arIJsonUri = [];     
         for(var e=0;e<maniJson["sequences"].length;e++){
               for(var ec=0; ec<maniJson["sequences"][e]["canvases"].length;ec++){
             var ece =  maniJson["sequences"][e]["canvases"][ec];
             var iJsonUri = ece["images"][0]["resource"]["service"]["@id"]+'/info.json';
             arIJsonUri.push(iJsonUri);      
         }
       }       
       viewer.open(arIJsonUri); 

これで、OpenSeadragonはManifestに記載されている画像を順番にページめくりするかのように表示してくれるようになるはずです。

この場合のmanifest URIの例としてはたとえば以下のものがあります。

https://www.dl.ndl.go.jp/api/iiif/10317557/manifest.json

サンプルはこちらです。

ここまで来れば、なんとなくIIIF ビューワっぽい感じになりましたね。 Manifestの中に用意されている他の情報を取り出して表示させたり、といったことは、ここまでやってきたことを応用すればできると思いますので色々試してみてください。

次回は、もう少し複雑なことをやってみましょうか。