🙆‍♀️

Mirador 4の拡大・縮小・回転の挙動を確認する

2024/06/26に公開

概要

Mirador 4の拡大・縮小・回転の挙動を変更する必要があり、その変更方法に関する備忘録です。

セットアップ

以下により、ローカルでMirador 4を起動します。

git clone https://github.com/projectmirador/mirador
cd mirador
pnpm i
pnpm start

ポート4444で起動します。

zoomIn時の処理のカスタマイズ

一例ですが、zoomInボタンをクリックした際の処理を以下のように変更してみます。

/src/components/ZoomControls.js
...
handleZoomInClick() {
    const { windowId, updateViewport, viewer } = this.props;

    updateViewport(windowId, {
    // zoom: viewer.zoom * 2,
      zoom: viewer.zoom * 1.1, // 追加
      rotation: viewer.rotation + 5, // 追加
      x: viewer.x * 1.1, // 追加
      y: viewer.y * 1.1, // 追加
    });
  }
...

結果、zoomInボタンを押した際に、中心が少しずれながら、拡大・回転が行われることがわかります。

https://youtu.be/wn1WxpTVpS4

これを応用することで、Mirador 3の拡大・縮小・回転等のカスタマイズを行うことができます。

immediateの設定

上記の例では、拡大や回転が完了するまで少し時間がかかっていました。これを即座に行いたい場合、以下のOpenSeadragonViewer.jsのcomponentDidUpdateをカスタマイズします。

viewerConfigオブジェクトのimmediatelyプロパティに基づき、拡大縮小や回転を即座に実施するかを設定できるようにします。

/src/components/OpenSeadragonViewer.js
...
componentDidUpdate(prevProps, prevState) {
    const {
      viewerConfig,
      canvasWorld,
    } = this.props;
    const { viewer } = this.state;
    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();
      const 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) {
      const { viewport } = viewer;

      const immediately = viewerConfig.immediately || false;

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

      if (viewerConfig.zoom !== viewport.zoomSpring.target.value) {
        viewport.zoomTo(viewerConfig.zoom, viewerConfig, immediately);
      }

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

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

そして、先のZoomControls.jsにおいて、immediately: trueを追加します。

/src/components/ZoomControls.js
...
handleZoomInClick() {
    const { windowId, updateViewport, viewer } = this.props;

    updateViewport(windowId, {
    // zoom: viewer.zoom * 2,
      zoom: viewer.zoom * 1.1,
      rotation: viewer.rotation + 5,
      x: viewer.x * 1.1,
      y: viewer.y * 1.1,
      immediately: true, // 追加
    });
  }
...

結果、以下のような挙動になります。

https://youtu.be/qfGo-WCQZoQ

以前の挙動に比べて、拡大や回転が即座に行われるようになりました。

拡大や回転を即座に行いたい理由

現在、複数のウインドウで拡大・縮小・回転処理を同期するプラグインを作成しています。

https://zenn.dev/nakamura196/articles/248bc0a393e128

この開発において、拡大・縮小・回転処理を即座に行わないと、うまく同期ができないケースがありました。

今回の修正では十分に考慮できていない点があるかと思いますが、いずれプルリクエストなどできればと思います。

まとめ

Mirador 4のプラグイン開発にあたり、参考になりましたら幸いです。

Discussion