本文へ移動
rdlabo.devdocs

ページとモーダルのサーフェス

ここでのレンダラーとは、ネイティブビューを作成し、レイアウトと外観を更新するプラグイン内の部分を指します。複数のネイティブコントロールを管理し、更新をバッチ化し、各コントロールを所有するページやモーダルを把握している場合に、このガイドを使います。Engineが画像の準備、スコープの再利用、ハンドオフの後処理を引き受けるため、オーバーレイごとに別々に実装する必要がありません。

単一のネイティブビューの場合は、CapacitorまたはCordovaの登録から始めてください。共通のモデルと制約は概念を参照してください。以下のAPIは既存レンダラー向けであり、それらのプラグインガイドで必要になる追加手順ではありません。この方式を選ぶ前に、ネイティブ初期化で基本のAPIと任意の設定を確認してください。

共通のライフサイクルを持つコントロールをまとめる

サーフェスは、ページやモーダル上のボタンなど、一緒にハンドオフする必要があるコントロールをまとめます。必ずしも1つのネイティブビューや画像ではありません。createWebProjectionSurfaceは準備済み画像とフォールバックのスコープを管理し、createWebProjectionSurfacesは複数のサーフェスのライフタイムを管理します。

背景ページが覆われても、前面のモーダルのコントロールまで覆われるとは限らないため、グループの分離が重要です。1つのライフサイクルを共有すると、独立した表示の判断が互いに干渉してしまいます。

たとえば、ツールバーボタンとタブバーを描画するプラグインは、背景ページと各モーダルに別々のサーフェスを使えます。

サーフェス ネイティブコンテンツ Web画像が役立つ場面
背景ページ ツールバーボタンとタブバー WebモーダルやPopoverがページのコントロールを覆う必要があるとき。
モーダル 閉じるボタンと確定ボタン ドラッグでモーダルが動くとき、または別のWebオーバーレイがコントロールを覆うとき。

モーダルを開くと、背景サーフェスは準備済み画像に切り替わり、モーダル自身のコントロールは適切な場合にネイティブのままにできます。閉じる際は、背景コントロールを現在の位置へ復元するよう要求します。画像はネイティブ更新の受理後に取り除かれます。サーフェスを分離することで、閉じたモーダルの画像や遅れた応答が、新たに見えるようになったページの所有権を取得するのを防ぎます。

既存のレンダラーに接続する

各段階をレンダラー内の対応するイベントに接続します。以下は別々のライフサイクル時点を示すもので、初期化中にまとめて実行するコードではありません。レンダラーはtransport、ソースIDとフレーム、受理済みリビジョン、既存の更新スケジューラーを提供します。この例のownerOf(element)は、コントロールを所有するページやモーダルを取得する、レンダラーの既存の処理です。

所有者が利用可能になったときにサーフェスを作成する

ネイティブコントロールのソースを、既存のフォールバックコンテナに対応付けます。コレクションは、同じ所有者への繰り返し更新でサーフェスを再利用します。ensureに渡す所有者はライフサイクルのキーであり、ソースのフィルターではありません。surfaces.considerはすべてのサーフェスへバッチを配信します。各サーフェスはeligibleで自らのコントロールだけを選びます。2つのサーフェスが同じフォールバックコンテナを管理してはいけません。

import { createWebProjectionSurface, createWebProjectionSurfaces, type WebProjectionSurface } from '@webview-native-ui/engine';

const surfaces = createWebProjectionSurfaces<HTMLElement, WebProjectionSurface>();
const projection = await surfaces.ensure(page, () =>
  createWebProjectionSurface(transport, {
    namespace: 'my-renderer',
    target: (source) => source.element,
    eligible: (source) => ownerOf(source.element) === page,
    wake: scheduleUpdate,
    blocked: () => transitionIsActive,
  }),
);

通常の更新中に準備し、表示の境界でハンドオフする

受理されたネイティブ更新が、準備する外観を提供します。ハンドオフの開始時はその準備済み画像を使い、終了時はすぐに画像を取り除くのではなく復元を要求します。サーフェスが画像を所有している間は、そのownersを通常のネイティブ描画から除外し、上を覆うWebレイヤーよりもライブコントロールが手前に出ないようにします。復元中の復帰画像の所有権にはvisibleOwnersを使います。画像を破棄するのは、通常のネイティブ更新の確認応答を受けた後だけです。

// 通常のネイティブ更新を受理した後:
surfaces.consider(acceptedRevision, sources);

// フレームワークがこの所有者の被覆または移動を通知したとき:
projection?.begin();

// その被覆または移動が終わったとき:
projection?.end();
// レンダラーの通常のネイティブ更新を送り、その確認応答で:
surfaces.updated(token, restoredIDs, acceptedRevision);

ページまたはレンダラーを破棄する

所有者を削除すると、遅れて完了する作成や復元によって、そのコントロールが復活することを防げます。レンダラー自身を破棄するときは、コレクションを破棄してください。

await surfaces.delete(page); // ページの破棄。
// レンダラーの終了処理時:
await surfaces.destroy();

配置と共有監視

レンダラーはネイティブIDとフレーム、ソースの所有権、配置方針、受理された更新の確認応答を提供します。フレームワークのライフサイクルイベントはEngineの外部に残ります。Engineは、任意のDOM変更からモーダルの意味を推定しません。

レンダラーが所有するフォールバックプロキシでは、canRelocate(target)が、begin(layer)によって渡されたオーバーレイレイヤーへホストを移すことを明示的に許可します。Engineは復元、失敗、破棄の後に、親と兄弟の順序を戻します。デフォルトではアプリのDOMを移動しません。アプリがプロキシの親を変更した場合、古い位置への復元よりもその変更を優先します。

コレクションは、外観、リサイズ、画面方向、ドキュメントの可視性のリスナーをサーフェス間で共有し、Engineが所有する画像イベントを無視します。レンダラーはignoreTargetで自身のプロキシイベントを除外できます。followMotion(moving, target)はレンダラーの既存の移動要素マップを使い、画像自身のホストがアニメーションする間だけ画像の基準位置を調整します。祖先のtransformはポーリングなしでも画像を移動させます。破棄時には、すべてのリスナーとスケジュール済みフレームを取り除きます。

繰り返しのensure呼び出しは、保留中の作成または既存の投影を共有します。削除、DOMの切断、レンダラーの破棄が発生すると、遅れて届いた結果が有効になるのを防ぎ、Engineがそれを破棄します。作成の失敗は再試行できます。レンダラーは既存のライフサイクルでページの破棄を通知し、通常の更新パス中にkeys()とvalues()を確認できます。コレクションは2つ目のDOM変更監視や継続的なポーリングループを追加しません。

利用側のレンダラーでハンドオフを検証する

オーバーレイの表示開始と終了、モーダルの移動、復元中の所有者の削除を確認してください。背景と前面はそれぞれのコントロールを維持し、遅れた確認応答が退場済みの所有者を復元してはいけません。外観を変えずに位置を変えて画像の再利用を確認し、その後コンテンツや寸法を変えて無効化を確認します。画像がない場合も確認し、オーバーレイの開始を遅らせず、通常のフォールバックを利用できるようにしてください。

Engineは所有権を調整しますが、レイヤーの選択とネイティブ配置を検証できるのは利用側のアプリケーションです。ネイティブハンドオフの契約に従い、iOSではNativeUICoveredSnapshots.handle、AndroidではNativeUISnapshots.handleを使ってネイティブ側を実装します。キャプチャ可能なネイティブの境界と、非表示にしてよいビューの全体を提供します。Engineは要求を検証して投影先の座標を変換します。通常のネイティブレイアウトの適用と、受理した更新の確認応答の通知は、引き続きレンダラーが行います。

異なる所有権の要件は、低レベルのWeb投影を参照してください。更新のスケジュールは独立しています。任意の更新キューは、レンダラーの調整方針に合う場合にだけ使います。