一键导入
map-interactions
How map movement, state, and geolocation work. Use this when modifying the map, its position/zoom, URL sync, or geolocation behaviour.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
How map movement, state, and geolocation work. Use this when modifying the map, its position/zoom, URL sync, or geolocation behaviour.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Guide for writing end to end tests using plawright. Use this when asked to write an end-to-end-test.
Official integration patterns for Mapbox GL JS across popular web frameworks (React, Vue, Svelte, Angular). Covers setup, lifecycle management, token handling, search integration, and common pitfalls. Based on Mapbox's create-web-app scaffolding tool.
Performance optimization patterns for Mapbox GL JS web applications. Covers initialization waterfalls, bundle size, rendering performance, memory management, and web optimization. Prioritized by impact on user experience.
基于 SOC 职业分类
| name | map-interactions |
| description | How map movement, state, and geolocation work. Use this when modifying the map, its position/zoom, URL sync, or geolocation behaviour. |
Map movements are always imperative — driven by direct user interaction (drag, zoom, click, geolocation trigger) — and never declarative (never derived from URL/query parameters).
The URL is updated after the map has moved, never the other way around. This one-way data flow (map → URL) prevents endless UI loops where a URL change moves the map, which updates the URL, which moves the map, etc.
user interaction → map moves → onMoveEnd / onZoomEnd fires → URL updated (shallow)
Never read position from the URL and feed it back into the map as a controlled value.
| File | Purpose |
|---|---|
src/modules/map/components/MapComponent.tsx | The main <ReactMapGL> wrapper. Renders the map, sources, layers, and controls. |
src/modules/map/hooks/useMap.tsx | MapContext — shares the MapRef instance and an isReady flag across the app. |
src/modules/map/hooks/useMapInteraction.ts | Mouse/touch handlers and the onViewStateChange callback that syncs map position → URL. |
src/modules/map/hooks/useMapStyle.ts | Manages dark/light map style and icon loading. Temporarily resets isReady during style switches. |
src/modules/app-state/hooks/useAppState.tsx | The global AppState context. Position is one slice of app state, serialised to/from URL query params. |
src/modules/app-state/app-state.tsx | Declares the appStateConfig — default position is { lat: 52.5, lon: 13.3, zoom: 10 } (Berlin). |
react-map-gl/mapbox <Map> with initialViewState (not viewState), making the map uncontrolled — it manages its own internal position.initialViewState is read from appState.position (parsed from URL on first render) and used only once.onMoveEnd and onZoomEnd both call onViewStateChange, which writes the new position back to the URL via setAppState(..., { routerOperation: "shallow" }). This uses window.history.replaceState so there is no navigation/re-render.MapContext (useMap()) by passing the ref={setMap} callback to <ReactMapGL>.isReady flips to true after onLoad completes (style loaded + icons loaded). Other parts of the app can check this before interacting with the map.map (MapRef | undefined), setMap, isReady, setIsReady.MapRef is react-map-gl's wrapper around mapboxgl.Map — it exposes flyTo, easeTo, getZoom, etc.isReady is false until the map style + icons are loaded, and is temporarily reset to false when switching between dark/light mode.onViewStateChange(event: ViewStateChangeEvent) — extracts { longitude, latitude, zoom } from the event and writes it to appState.position with a shallow router operation (no Next.js navigation, just history.replaceState).position (returned to MapComponent for initialViewState) is always read from appState.position.onMouseClick — resolves clicked features and navigates to the feature URL via the app-state-aware router.useState), toggled on mouseEnter/mouseLeave over interactive layers.GeolocateControl is rendered inside the map with trackUserLocation enabled. This shows the blue dot and follows the user.setGeolocateControl) is used instead of a plain useRef because react-map-gl's GeolocateControl expects a ref callback, not a mutable ref object.geoControlRef.current.trigger() is called once after the map is ready (isReady flips true). This programmatically starts the browser geolocation flow — identical to the user clicking the geolocate button.onGeolocate fires a handleGeolocate callback that calls map.flyTo() to the reported coordinates, zooming to at least 15.useGeolocationPermission), which asks for permission via navigator.geolocation.getCurrentPosition.AppState is derived from URL search params on each render (getAppStateFromSearchParams).setAppState merges new values, serialises to query params, and pushes/replaces/shallow-updates the URL.routerOperation: "shallow" (used by map position updates) calls window.history.replaceState directly — no Next.js router cycle, no re-render.localStorage so returning users resume where they left off (when no URL params are present).viewState on the map — always use initialViewState to keep it uncontrolled.useEffect watching query params). The URL reflects the map, not the other way around.map.flyTo() / map.easeTo() / map.jumpTo() on the MapRef obtained from useMap().onMoveEnd handler will automatically sync the new position back to the URL.isReady — the map instance exists before icons/style are loaded, but interacting too early can cause errors.