Skip to content

Hold ground image removals until the style can be edited; drop the clear() overrides - #17

Merged
wf9a5m75 merged 2 commits into
developfrom
fix/overlay-clear-order
Nov 8, 2026
Merged

wf9a5m75 merged 2 commits into
developfrom
fix/overlay-clear-order

Conversation

@wf9a5m75

@wf9a5m75 wf9a5m75 commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

なぜ

clearOverlays() の後も、この地図では GroundImage が残っていました。またポリライン・サークルは、js-sdk-core の clear() の呼び順の問題を、このプロバイダ側の clear() の上書きで回避していました。

GroundImage が残る(2 つ目のコミット)

GroundImage のコントローラは core を継承しない独自のもので、renderer.removeGroundImage は canEditStyle() が false のとき何もせずに戻っていました。一方でコントローラは削除を頼んだ時点で state を忘れるので、その画像は二度と消されません。

canEditStyle() は styledata で isStyleLoaded() を見て切り替わります。他のオーバーレイがソースを書き換えた直後は isStyleLoaded() が一瞬 false になるので、ポリライン・サークル等を先に消す clearOverlays() では毎回これに当たっていました。

調べる途中で分かったこと(この PR では直していません): 検証用のページでは、styleReady が約 0.3 秒ごとに true / false を往復し続けていました。styledata(loaded=false)→ idle → resyncAll() → 各コントローラの再同期がまた styledata を起こす、の繰り返しで、描画中のどの時点でも canEditStyle() が false の可能性があります。6 種類の再同期を 1 つずつ止めても往復は続き、全部止めると止まりました(複数の再同期がそれぞれ styledata を起こしています)。別の問題として扱うべきだと思います。

clear() の上書きを消す(1 つ目のコミット)

js-sdk-core の clear() が「onRemove → manager.clear() → onPostProcess」の順になった(js-sdk-core の同じ PR)ので、ポリライン・サークルの clear() の上書き(super.clear() の後に描き直す)を消しました。clear() は core から同じシグネチャで継承されるので、公開 API の実体は変わりません(API スナップショットから上書き分の行が消えるだけです)。

このコミットは js-sdk-core の新しい版の公開と、依存(今は ^0.3.1)の引き上げが前提です。 依存を上げるコミットはこの PR に入れていません。js-sdk-core を公開した後で、その版に上げてからマージしてください。

古い core のままこのコミットを入れた場合: 前の担当の確認(古い core で上書きだけを消したビルド)では、ラスターレイヤーが無い画面だと、clearOverlays() の後もポリライン・サークルが残るはずです(ラスターがあると、その再描画のついでに消えるので見た目では分かりにくい)。

何を変えたか

  • MapTilerGroundImageOverlayRenderer: スタイルを編集できない間に来た削除を pendingRemovals に残し、flushPendingRemovals()(@internal)で反映します。同じ id がその前に追加し直されたら、残していた削除は取り消します。
  • MapTilerGroundImageController.resync(): 最初に flushPendingRemovals() を呼びます。resync() はスタイルが編集できるようになった(styleReady が false → true になった)ときに呼ばれます。
  • test/GroundImageRemoval.test.mjs を足しました(修正前は 1 本目が失敗)。
  • ポリライン・サークルのコントローラの clear() の上書きを消しました(上記)。
  • API スナップショット: private の 2 行の追加と、継承に任せた clear() の 2 行が消えただけです。

関連 PR(同じ修正の一式)

fix/overlay-clear-order は次の 21 リポジトリにまたがります。

1. core(3 本は互いに独立。先にマージ・公開してください)

2. Android プロバイダ(core が無くても単独で効く修正。ただしポリライン・ポリゴン・GroundImage・ラスターの消え残りは core 側で直るので、core と合わせて初めて clearOverlays() が全部消えます)

3. iOS プロバイダ(ios-sdk-core のマージ・公開の後。clearOverlays() からコントローラの clear() を呼ぶ変更は、core の呼び順の修正が無いと GL 系で描き直しが起きて消えません)

4. web プロバイダ(js-sdk-core の新しい版を npm に公開し、依存(今は ^0.3.1)を引き上げてから。理由は各 PR の本文に)

マージの順番: core 3 本 → core の公開 → Android / iOS プロバイダ → js-sdk-core の npm 公開と依存の引き上げ → web プロバイダ。

検証

  • npm test(新しいテストを含めてすべて通過)、tsc --noEmit、npm run build。
  • node scripts/api-surface.mjs check(react-sdk): 上記以外の差分なし。
  • Playwright(このブランチのプロバイダと、js-sdk-core の同じ PR のビルド)で下の 7 段階を確認しました。修正前は clear 後に GroundImage だけが残っていました。修正後は MapLibre / Mapbox / Mappls / MapTiler / TomTom の 5 本とも何も残らず、地図のスタイルにも GroundImage のレイヤーが残っていないこと(getLayer('mc-gimg-lyr-GI') が無い)を確かめました。
  • refactor/polygon-controller の OPEN な PR とは git merge-tree で衝突しないことを確かめました。

実機・ブラウザでの確認(共通の手順)

同じ手順で、ポリゴン・ポリライン・サークル・GroundImage・ラスター・マーカーを出し、追加 → 更新(色・半径・不透明度)→ 一部削除(ポリゴン・サークル・ラスター)→ 戻す → clearOverlays() → clear 後に同じ state を in-place で書き換え → 同じ id・同じ内容の state を作り直して送り直す、の 7 段階をスクリーンショットで比べました。検証用のページはコミットしていません。

clearOverlays() の後 clear 後の in-place 更新 作り直して送り直す
Android(タブレット)MapLibre / Mapbox / Mappls / Google / OMM 何も残らない 戻らない 全部戻る
iOS(iPad 実機)MapLibre / Mapbox / MapTiler / Mappls / Google 何も残らない 戻らない 全部戻る
web(Playwright)MapLibre / Mapbox / Mappls / MapTiler / TomTom 何も残らない 戻らない 全部戻る

追加・更新・削除・戻すの 4 段階の見た目は修正前と同じでした。clear 後の振る舞い(in-place の更新では戻らず、顔ぶれが変わるか作り直された state が来たら全部描き直す)は、3 プラットフォームの core の collector と同じです。

確認できていないもの

  • デザイン変更中の削除(setStyle の最中)は、単体テストの「スタイルを編集できない間の削除」で代わりに確かめただけで、ブラウザでは試していません。

They redrew after super.clear() because js-sdk-core's clear() called
onPostProcess before emptying the manager (polyline) or not at all
(circle), so this provider's redraw-from-manager renderer kept drawing
what clear() removed. js-sdk-core now runs onRemove, manager.clear(),
onPostProcess, which redraws an empty layer.

clear() is still there, inherited from the core controller with the same
signature; the API snapshot only stops listing the override.

Requires the js-sdk-core release with that change (MapConductor/js-sdk-core
fix/overlay-clear-order). Against an older core, clearOverlays() leaves
polylines and circles drawn until something else redraws them.
removeGroundImage returned early while canEditStyle() was false, and the
controller had already forgotten the state, so the image stayed on the
map for good. canEditStyle follows isStyleLoaded(), which turns false
right after other overlays rewrite their sources; clearOverlays() clears
those first, so the ground image survived every clearOverlays().

The renderer now keeps such removals and applies them from the
controller's resync(), which runs when the style becomes editable again.
Adding the same id again before then cancels the held removal.

GroundImageRemoval.test.mjs covers both.
This was referenced Nov 8, 2026
@wf9a5m75
wf9a5m75 merged commit 96614a7 into develop Nov 8, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant