One Logo Pool Ball
wwwwwwwwwwwwwwwwwww

Map

One map on both platforms, MapKit on iOS and Google Maps on Android

One.UI.Map on iOS: MapKit with markers, a walking route, and a radius over San Francisco

One.UI.Map is one map API on both platforms: MapKit on iOS and Google Maps on Android.

Usage

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 key

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,
},
},
},
})

API reference

Every prop is optional. An empty map shows the default camera over San Francisco. Colors are #rrggbb or #rrggbbaa strings.

PropsTypeDescription
styleStyleProp<ViewStyle>Sizes the map.
StyleProp<ViewStyle>Sizes the map.
testIDstringTest identifier for the native view.
stringTest identifier for the native view.
accessibilityLabelstringLabel read by screen readers.
stringLabel read by screen readers.
cameraPositionCameraPositionCenter and Google zoom. Applied on mount and whenever the value changes.
CameraPositionCenter 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.
EventsTypeDescription
onCameraMove(event: { coordinates: Coordinates; zoom: number }) => voidOnce when a pan or zoom gesture ends, with the new camera.
(event: { coordinates: Coordinates; zoom: number }) => voidOnce 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) => voidA 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 }) => voidThe map was tapped away from a marker. Marker taps never also fire this.

Shapes

CameraPositionTypeDescription
coordinatesCoordinatesThe center.
CoordinatesThe center.
zoomnumberGoogle zoom level, the same scale on both platforms.
numberGoogle zoom level, the same scale on both platforms.
CoordinatesTypeDescription
latitudenumberDegrees north.
numberDegrees north.
longitudenumberDegrees east.
numberDegrees east.
MapMarkerTypeDescription
idstringUnique among markers.
stringUnique among markers.
coordinatesCoordinatesWhere the pin sits.
CoordinatesWhere the pin sits.
titlestringShown with the pin.
stringShown with the pin.
tintColorstringPin color.
stringPin color.
MapPolylineTypeDescription
idstringUnique among polylines.
stringUnique among polylines.
coordinatesreadonly Coordinates[]The points, in order.
readonly Coordinates[]The points, in order.
colorstringLine color.
stringLine color.
widthnumberLine width in points.
numberLine width in points.
MapPolygonTypeDescription
idstringUnique among polygons.
stringUnique among polygons.
coordinatesreadonly Coordinates[]The corners, in order.
readonly Coordinates[]The corners, in order.
colorstringFill color.
stringFill color.
lineColorstringOutline color.
stringOutline color.
lineWidthnumberOutline width in points.
numberOutline width in points.
MapCircleTypeDescription
idstringUnique among circles.
stringUnique among circles.
centerCoordinatesThe center.
CoordinatesThe center.
radiusnumberRadius in meters.
numberRadius in meters.
colorstringFill color.
stringFill color.
lineColorstringOutline color.
stringOutline color.
lineWidthnumberOutline width in points.
numberOutline width in points.

Behavior

Left out on purpose: custom marker views and callouts, user location, map type and styling, tilt and bearing, gesture toggles, and imperative camera refs.

iOSAndroidWeb
Native viewMapKitGoogle MapsRenders nothing
KeyNonegoogleMapsApiKey, or mounting throwsNone

On web, pair it with a web map library.

iOS search and directions

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.