IIIFビューア Mirador のバージョン4向けに、物理寸法のルーラーを表示するプラグイン mirador-physical-ruler を開発しました。

背景

デジタルアーカイブで公開されている史料画像を閲覧する際、実物の大きさが直感的にわかりにくいという問題があります。IIIFの仕様には Physical Dimensions service が定義されており、マニフェストのcanvasに物理スケール情報を埋め込むことができます。

Mirador 2向けには dbmdz/mirador-plugins の physicalRuler や、Mirador 3向けには mirador-ruler-plugin が存在しますが、Mirador 4対応のものは確認できませんでした。そこで新たに開発しました。

全体表示

左が海東諸国紀(21.2×32.6cm)、右が正保琉球国悪鬼納島絵図写(621.6×353.7cm)です。サイズが大きく異なる史料でも、それぞれの実寸に応じたルーラーが表示されます。

全体表示。2つのウィンドウにそれぞれルーラーが表示されている

ルーラーの表示

canvasにphysdim serviceが設定されていれば、上端と左端にスケールルーラーがSVGで描画されます。海東諸国紀(横21.2cm)では0〜20cmの目盛りが表示されています。

海東諸国紀のルーラー。0〜18cmの目盛りが上端と左端に表示されている

琉球絵図(横621.6cm)のような大型史料では、目盛りの単位が自動的に調整され、100cm刻みで表示されます。

琉球絵図のルーラー。100〜500cmの目盛りが表示されている

ズーム時の自動調整

ズームインすると目盛り間隔が細かくなり、より詳細な寸法を確認できます。

ズームイン時のルーラー。目盛り間隔が細かくなっている

設定パネル

左上の歯車ボタンから以下を変更できます。

  • フォントサイズ
  • ルーラー幅
  • 目盛りサイズ(大・小)
  • 表示単位(mm / cm / in)
  • 背景の透明度

設定パネル

外部マニフェストの読み込み

デモページでは ?manifest= パラメータで任意のマニフェストURLを指定できます。

https://nakamura196.github.io/mirador-physical-ruler/?manifest=https://example.com/manifest.json

使い方

npm install mirador-physical-ruler
import Mirador from 'mirador';
import { createPlugin } from 'mirador-physical-ruler';

const plugin = createPlugin({
  color: '#ffffff',
  thickness: 34,
});

Mirador.viewer(
  {
    id: 'mirador',
    windows: [{ manifestId: 'https://example.com/manifest.json' }],
  },
  plugin
);

マニフェストへのphysdim serviceの追加

canvasの service に以下のように記述します。

{
  "service": [
    {
      "@context": "http://iiif.io/api/annex/services/physdim/1/context.json",
      "profile": "http://iiif.io/api/annex/services/physdim",
      "physicalScale": 0.04739,
      "physicalUnits": "mm"
    }
  ]
}

physicalScale は1ピクセルあたりの物理サイズ(mm単位)です。実物の幅(mm)をcanvasのwidth(px)で割って求めます。スキャン解像度がわかっている場合は 25.4 / dpi で計算できます。

デモで使用した史料

デモでは東京大学史料編纂所が公開する2点の史料を使用しています。

技術的な実装

Mirador 4のプラグインAPIは wrap モードで OpenSeadragonViewer コンポーネントをラップする形式です。OSDReferences.get(windowId) でOpenSeadragonのviewerインスタンスを取得し、getBoundsNoRotate() からビューポートの表示範囲を計算しています。

OSDのビューポート座標系ではcanvasピクセル座標がそのまま使われるため、スクリーンピクセルへの変換は以下の式になります。

pixelsPerUnit (screen px/mm) = containerWidth / (bounds.width × physicalScale)

ズーム・パン・アニメーションイベントを requestAnimationFrame でバッチ処理し、目盛り間隔は niceInterval 関数で 1, 2, 5, 10, 20, 50… の系列から自動選択しています。