
One.UI.Map is one map API on both platforms: MapKit on iOS and Google Maps
on Android.
zoom, seeded from props.import { One } from 'one'
<One.UI.Map style={{ flex: 1 }} cameraPosition={{ coordinates: { latitude: 37.7955, longitude: -122.3937 }, zoom: 12, }} markers={[ { id: 'ferry', coordinates: { latitude: 37.7955, longitude: -122.3937 }, title: 'Ferry Building', tintColor: '#ff3b30', }, ]} onCameraMove={({ coordinates, zoom }) => recordCamera(coordinates, zoom)} onMarkerClick={(marker) => selectPlace(marker.id)} onMapClick={({ coordinates }) => dropPin(coordinates)}/>The camera seeds from cameraPosition and seeds again only when its value
changes. In between, people pan and zoom freely. Never feed onCameraMove
back into cameraPosition; that seeds the camera at the end of every gesture
and fights the pan.
Android needs a maps key in the app manifest, or mounting throws. The Maps SDK compiles into Android builds only when the key is set.
one({ native: { app: { android: { googleMapsApiKey: process.env.GOOGLE_MAPS_API_KEY, }, }, },})Every prop is optional. An empty map shows the default camera over San
Francisco. Colors are #rrggbb or #rrggbbaa strings.
| Props | Type | Description |
|---|---|---|
styleStyleProp<ViewStyle>Sizes the map. | StyleProp<ViewStyle> | Sizes the map. |
testIDstringTest identifier for the native view. | string | Test identifier for the native view. |
accessibilityLabelstringLabel read by screen readers. | string | Label read by screen readers. |
cameraPositionCameraPositionCenter and Google zoom. Applied on mount and whenever the value changes. | CameraPosition | Center and Google zoom. Applied on mount and whenever the value changes. |
markersreadonly MapMarker[]Pins. Ids must be unique. | readonly MapMarker[] | Pins. Ids must be unique. |
polylinesreadonly MapPolyline[]Open lines through coordinates. | readonly MapPolyline[] | Open lines through coordinates. |
polygonsreadonly MapPolygon[]Closed, filled shapes. | readonly MapPolygon[] | Closed, filled shapes. |
circlesreadonly MapCircle[]Filled circles with a radius in meters. | readonly MapCircle[] | Filled circles with a radius in meters. |
| Events | Type | Description |
|---|---|---|
onCameraMove(event: { coordinates: Coordinates; zoom: number }) => voidOnce when a pan or zoom gesture ends, with the new camera. | (event: { coordinates: Coordinates; zoom: number }) => void | Once when a pan or zoom gesture ends, with the new camera. |
onMarkerClick(marker: MapMarker) => voidA marker was tapped. Receives the marker object from props, matched by id. | (marker: MapMarker) => void | A marker was tapped. Receives the marker object from props, matched by id. |
onMapClick(event: { coordinates: Coordinates }) => voidThe map was tapped away from a marker. Marker taps never also fire this. | (event: { coordinates: Coordinates }) => void | The map was tapped away from a marker. Marker taps never also fire this. |
| CameraPosition | Type | Description |
|---|---|---|
coordinatesCoordinatesThe center. | Coordinates | The center. |
zoomnumberGoogle zoom level, the same scale on both platforms. | number | Google zoom level, the same scale on both platforms. |
| Coordinates | Type | Description |
|---|---|---|
latitudenumberDegrees north. | number | Degrees north. |
longitudenumberDegrees east. | number | Degrees east. |
| MapMarker | Type | Description |
|---|---|---|
idstringUnique among markers. | string | Unique among markers. |
coordinatesCoordinatesWhere the pin sits. | Coordinates | Where the pin sits. |
titlestringShown with the pin. | string | Shown with the pin. |
tintColorstringPin color. | string | Pin color. |
| MapPolyline | Type | Description |
|---|---|---|
idstringUnique among polylines. | string | Unique among polylines. |
coordinatesreadonly Coordinates[]The points, in order. | readonly Coordinates[] | The points, in order. |
colorstringLine color. | string | Line color. |
widthnumberLine width in points. | number | Line width in points. |
| MapPolygon | Type | Description |
|---|---|---|
idstringUnique among polygons. | string | Unique among polygons. |
coordinatesreadonly Coordinates[]The corners, in order. | readonly Coordinates[] | The corners, in order. |
colorstringFill color. | string | Fill color. |
lineColorstringOutline color. | string | Outline color. |
lineWidthnumberOutline width in points. | number | Outline width in points. |
| MapCircle | Type | Description |
|---|---|---|
idstringUnique among circles. | string | Unique among circles. |
centerCoordinatesThe center. | Coordinates | The center. |
radiusnumberRadius in meters. | number | Radius in meters. |
colorstringFill color. | string | Fill color. |
lineColorstringOutline color. | string | Outline color. |
lineWidthnumberOutline width in points. | number | Outline width in points. |
Left out on purpose: custom marker views and callouts, user location, map type and styling, tilt and bearing, gesture toggles, and imperative camera refs.
| iOS | Android | Web | |
|---|---|---|---|
| Native view | MapKit | Google Maps | Renders nothing |
| Key | None | googleMapsApiKey, or mounting throws | None |
On web, pair it with a web map library.
One.iOS.Map also supports MapKit Look Around through the generated SwiftUI
lookAroundViewer style. Keep isPresented controlled; MapKit asks for a scene
at the supplied coordinates and calls onChange(false) when the viewer closes
or no scene is available. Look Around needs network access and is available on
iOS 17 or later.
const [showLookAround, setShowLookAround] = useState(false)
<One.iOS.Map latitude={37.7955} longitude={-122.3937} markers={[]} style={{ height: 240 }} swiftStyle={{ lookAroundViewer: { isPresented: { value: showLookAround, onChange: setShowLookAround }, latitude: 37.7934, longitude: -122.3950, }, }}/>// Set showLookAround to true from a button to present the viewer.One.MapServices uses MapKit’s local search and route service. It needs a
network connection, but no location permission when you provide coordinates.
The map view’s marker and polyline props accept coordinates from these results.
const center = { latitude: 37.7955, longitude: -122.3937 }const places = await One.MapServices.search('Ferry Building', center, 3000)const suggestions = await One.MapServices.autocomplete('Ferry Bu', center, 3000)const selected = suggestions[0]if (selected) { const place = await One.MapServices.resolveSuggestion(selected.id) // place has the selected suggestion's name, address, and coordinates.}const route = await One.MapServices.directions( center, { latitude: 37.7786, longitude: -122.3893 }, 'walking')// route.polyline can be passed to One.UI.Map's polylines coordinates.search(query, center, radiusMeters = 5000) returns names, addresses, and
coordinates. Radius must be 100 to 50,000 metres and hints the search region;
MapKit may return results outside that region. directions(origin, destination, transport = 'driving') returns the first route’s distance in metres, expected
travel time in seconds, polyline coordinates, and instruction steps. The
transport is driving or walking. Search can return an empty array. Invalid
input rejects with E_MAP_INPUT; service and routing failures reject with
E_MAP_SEARCH and E_MAP_DIRECTIONS.
autocomplete(query, center, radiusMeters = 5000) returns MapKit text
suggestions with an id, title, and subtitle. Pass the selected id to
resolveSuggestion(id) to get its exact MapKit place. IDs remain valid until
the next successful autocomplete result replaces them. A newer query cancels
an unfinished query, which rejects with E_MAP_CANCELED; handle that when
updating suggestions as someone types. Invalid input or an old ID rejects
with E_MAP_INPUT. MapKit failures use E_MAP_AUTOCOMPLETE or E_MAP_SEARCH;
a query that does not finish in 20 seconds uses E_MAP_TIMEOUT. See
Apple’s MapKit completion guide
for how suggestion fragments are produced.
The service namespace One.MapServices is implemented on iOS. On Android only search runs natively, on the platform geocoder bounded by the same center and radius validation; autocomplete resolves [], and resolving a suggestion or requesting directions rejects with MapServices.<verb> needs an iOS or Android build, because Android has no platform autocomplete or directions service. On web, search and autocomplete resolve []; resolving a suggestion or requesting directions rejects the same way.
Edit this page on GitHub.