Skip to content

Map: add side-by-side swipe comparison rendering driven through the plugin event bus #145

@slesaad

Description

@slesaad

Map: add side-by-side swipe comparison rendering driven through the plugin event bus

Motivation

Missions often need to visually compare two map states — two different layers, or the same layers at two different points in time — by dragging a divider across the map and revealing one state on each side. Today the map can only toggle whole layers on or off; there is no way to show different content on the left and right of a draggable divider.

There is also no clean way for a tool to ask the map to do this. The plugin architecture requires tools to stay independent and talk to the rest of the system only through the event bus — they must not reach into rendering internals. So this comparison/swipe behavior has to exist as a core map capability that a tool can drive entirely through events. This issue adds that primitive. A separate Comparison tool will consume it.

How it should work

  • A consumer (a tool/plugin) can turn on a comparison swipe mode on the map: a draggable vertical divider appears over the map.
  • The consumer specifies what renders on each side — a set of layers for the left, and a set for the right — and, for the date use case, an optional date pinned to each side.
  • Dragging the divider reveals more or less of each side. Left of the divider shows the left configuration; right of it shows the right configuration.
  • It stays consistent with the timeline: when the active date changes, each side updates its time-enabled layers according to the date assigned to that side (or the global date when a side isn't pinned to a specific date).
  • The consumer can update the sides live (swap layers, change a side's date) and turn the mode off, returning the map to a normal single view.
  • Everything above is reachable through the plugin event bus — a tool can drive it through events and requests alone, without touching map rendering directly. The capability emits events when the divider moves and when the mode toggles, so tools can react.

Done when

  • With comparison mode on, a draggable divider appears over the 2D map; dragging it reveals the left configuration on the left and the right configuration on the right.
  • A consumer can set and replace which layers render on each side — and assign a date to each side — through the event bus alone, with no direct map or rendering calls.
  • Changing the timeline date updates time-enabled layers on each side according to that side's assigned date.
  • Turning comparison mode off restores the normal single map view.
  • Divider position and mode on/off are observable as events other tools can subscribe to.
  • A consumer never needs to import or reach into map internals to use any of the above.

Out of scope

  • The Comparison tool UI/panel itself — that's a separate issue; this is only the map-side capability it consumes.
  • 3D / globe comparison — see the open question; can be a follow-up.
  • On-demand / floating panels.

Open questions

  • 2D only, or also 3D? Recommend delivering the 2D map capability first and treating 3D/globe swipe as a follow-up, since the clipping approach differs substantially between the two engines.
Draft implementation plan — written as of abef1d7 on 2026-06-15. Rough guide; re-verify against latest code.

Current behavior

  • Layer visibility is all-or-nothing per layer; there is no per-side or clipped rendering anywhere in the codebase (no side-by-side / swipe / clip mechanism exists).
  • The plugin event bus (on / off / emit / request / provide, plus a forPlugin namespacing wrapper) is implemented and is the intended integration surface. Core modules own the map:, layers:, time: namespaces; plugins use plugin:<id>:*.
  • Time-enabled layers update on date change driven by the timeline; time:change-style events flow over the bus. The time machinery assumes a single globally-active date.

Where the change lands & rough plan

  • Add a swipe/clip rendering mechanism to the 2D map engine: clip the relevant layer/tile panes to the left or right of a draggable divider (a leaflet "side-by-side" style pane clip is the conventional approach).
  • Model two sides, each a set of layer ids plus an optional pinned date. When the active date changes, resolve each side's time-enabled layers against that side's date.
  • Expose a small set of provide/request handlers and events on the event bus under the core map: namespace — enable/disable comparison, set a side's config, get/observe the divider position — so tools drive it without direct coupling. Emit events on divider move and on mode change.

⚠️ Gotcha: rendering two date-versions of the same time-enabled layer at once (the compare-dates case) likely means instantiating a second set of layer renderers for the right side. The existing time machinery assumes one globally-active date, so resolving "what does this side show at its date" without disturbing global timeline state is the hard part — budget for it.

References

Understood to be snapshot-accurate only:

  • src/essence/mmgisAPI/mmgisAPI.js — event bus and the forPlugin namespacing wrapper.
  • src/essence/Basics/Map_/Map_.js — 2D/3D rendering engine.
  • src/essence/Basics/TimeControl_/ — timeline and time-change events.
  • docs/adr/20260209-plugin-communication-model.md — the plugin communication model (event bus, namespaces, why tools stay decoupled).
  • Prototype (visual reference for the divider/swipe behavior): https://visualization-tool-prototype.netlify.app/

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions