Mirador 3でビューポートが設定した制約を満たすようにズームを行う

2023/07/11に公開

概要

Mirador 3で特定の領域にズームにするには、以下に記載があるような方法で行います。

https://github.com/ProjectMirador/mirador/wiki/M3---Mirador-3-Frequently-Asked-Questions#q-how-do-i-change-the-view-of-an-image-to-zoom-to-a-certain-area

具体的には以下です。

// Box to zoom to
const boxToZoom = {
  x: 1420,
  y: 1831,
  width: 800,
  height: 1195
};

const zoomCenter = {
  x: boxToZoom.x + boxToZoom.width / 2,
  y: boxToZoom.y + boxToZoom.height / 2
};
var action = Mirador.actions.updateViewport(windowId, {
  x: zoomCenter.x,
  y: zoomCenter.y,
  zoom: 1 / boxToZoom.width
});

miradorInstance.store.dispatch(action);

内部的にはOpenSeadragonのpanTozoomToが使用されているようでした。

この時の課題として、zoomToは以下の記事にあるように、constraintsを無視して拡大するようでした。

https://github.com/openseadragon/openseadragon/issues/881

これに対して、以下の記事で示したように、viewer.viewport.applyConstraints();の処理を追加することで、constraintsを守った拡大ができるようになりました。

https://zenn.dev/nakamura196/articles/66f0c00d51eb6a

以下、強引ではありますが、npmでインストールしたMiradorに対して、上記の設定を行う方法を紹介します。

Miradorの編集

以下でMiradorをインストールします。

npm install mirador

node_modules以下にmiradorフォルダが作成されます。

その中にある以下のファイルに対して、viewport.applyConstraints();を追加する例を示します。

node_modules/mirador/dist/es/src/components/OpenSeadragonViewer.js
...
{
    key: "componentDidUpdate",
    value: function componentDidUpdate(prevProps, prevState) {
      var _this$props2 = this.props,
          viewerConfig = _this$props2.viewerConfig,
          canvasWorld = _this$props2.canvasWorld;
      var viewer = this.state.viewer;
      this.apiRef.current = viewer;

      if (prevState.viewer === undefined) {
        if (viewerConfig) {
          viewer.viewport.panTo(viewerConfig, true);
          viewer.viewport.zoomTo(viewerConfig.zoom, viewerConfig, true);
          viewerConfig.degrees !== undefined && viewer.viewport.setRotation(viewerConfig.degrees);
          viewerConfig.flip !== undefined && viewer.viewport.setFlip(viewerConfig.flip);
        }

        this.addAllImageSources(!viewerConfig);
        return;
      }
      
      if (!this.infoResponsesMatch(prevProps.infoResponses) || !this.nonTiledImagedMatch(prevProps.nonTiledImages)) {
        viewer.close();
        var canvasesChanged = !isEqual(canvasWorld.canvasIds, prevProps.canvasWorld.canvasIds);
        this.addAllImageSources(canvasesChanged || !viewerConfig);
      } else if (!isEqual(canvasWorld.layers, prevProps.canvasWorld.layers)) {
        this.refreshTileProperties();
      } else if (viewerConfig && !this.osdUpdating) {
        var viewport = viewer.viewport;

        if (viewerConfig.x !== viewport.centerSpringX.target.value || viewerConfig.y !== viewport.centerSpringY.target.value) {
          viewport.panTo(viewerConfig, false);
        }

        if (viewerConfig.zoom !== viewport.zoomSpring.target.value) {
          viewport.zoomTo(viewerConfig.zoom, viewerConfig, false);
          viewport.applyConstraints(); // ここを追加
        }

        if (viewerConfig.rotation !== viewport.getRotation()) {
          viewport.setRotation(viewerConfig.rotation);
        }

        if (viewerConfig.flip !== viewport.getFlip()) {
          viewport.setFlip(viewerConfig.flip);
        }
      }
    }
    ...

上記の設定により、Mirador.actions.updateViewportでズームした際に、constraintsを守った拡大ができるようになりました。

まとめ

本来はMiradorのソースコードを修正してビルドするほうがよいと思いますが、Miradorのビルドがうまくいかず、代替策として、ビルド済みのファイルを修正しました。

ソースコードから修正する方法も引き続き調査を行いますが、他の方の参考になりましたら幸いです。

Discussion