Skip to content

Mall directory ​

Three floors, 49 tenants, search that jumps to the shop and zooms in on it. The plan is a plain SVG file — the names, logos and opening hours come from data, and every shop is clickable because it is a shape with an id.

What the library is doing here ​

Bindingeach <path id="u-101"> in the SVG is matched to a record by id; nothing about the tenants is stored in the file
LabelsContentPlugin places names inside the shapes and swaps in a logo where it fits, a shortened name where it does not, and the unit number as a last resort
ZoomZoomPlugin handles wheel, drag and pinch, and focusElement() flies to the shop picked in the list
Hovera render callback builds the directory entry — the logo the plan may have had no room for, the category, the level, the hours. placement: 'cursor', so it travels with the pointer the way a tooltip on a map does
HighlightsetHighlight('found', [id]) paints the match — the style lives in config, not in the SVG
FloorssetSrc() swaps the plan and keeps the same client, subscriptions and plugins

The popup is mounted on document.body by the library, which is why its styles live in a plain <style> block rather than a scoped one.

Everything else on this page — the search box, the result list, the card — is ordinary Vue. The library draws the map and tells you what was clicked; the product around it stays yours.

The plan itself ​

scripts/gen-mall.mjs generates the three floors, so the geometry is reproducible rather than hand-drawn once. Vertical cores — escalators, lifts, stairs — are declared once and shared by every level, which means they line up in plan across floors.

Each file also carries a hidden nav layer: a graph of the gallery with data-links between nodes and data-vertical on the ones that sit at a core. The core ignores that layer (role: 'data'), and a routing plugin can read it through getLayer('nav').

Facility icons are Material Design Icons inlined at generation time.

How the content plugin works → · Zoom and pan →