In this post we will be integrating multiple mapbox api's like Search, Retrieve, Geocoding, Reverse Geocoding, POIs, Directions.
Directions
The Mapbox Directions API will show you how to get where you're going. With the Directions API, you can:
Calculate optimal driving, walking, and cycling routes using traffic- and incident-aware routing
Produce turn-by-turn instructions
Produce routes with up to 25 coordinates for the driving, driving-traffic, walking, and cycling profiles
Calculate routes for electric vehicles to reach destinations with optimal charging stops as well as battery prediction
https://docs.mapbox.com/api/navigation/directions/
Search
The Mapbox Search Service includes two APIs: the Mapbox Geocoding API and the Mapbox Search API(to enable mapbox search feature dev need to connect with mapbox sales for enabling it).
https://docs.mapbox.com/api/search/
1. Geocoding
The Mapbox Geocoding API allows you to do forward and reverse geocoding operations. Forward Geocoding takes text in the form of an address or place and converts it to geographic coordinates (latitude/longitude). Reverse geocoding takes geographic coordinates (latitude/longitude) and converts it into an address or place in text form.
https://docs.mapbox.com/api/search/geocoding/
2. Search
The Mapbox Search API enables search suggestions and feature retrieval for an interactive Search experience.
The Search API includes six different endpoints: /suggest, /retrieve, /forward, /permanent/forward, /reverse, and /permanent/reverse.
https://docs.mapbox.com/api/search/search/
API COLLECTION:
- GET(Direction api)
curl --location --request GET 'https://api.mapbox.com/directions/v5/mapbox/driving/-122.42,37.78;-77.03,38.91?geometries=geojson&access_token=pk.eyJ1IjoiZGVlcGFrMTIyMSIsImEiOiJjbDhiZXQ5cmEwcXhzM3FvNTFhNDNpNms3In0.x6FPXW7P3lIWTKPs6PMaJA'
- GET(Gives suggestion list of inputted text)
curl --location --request GET 'https://api.mapbox.com/search/v1/suggest/mec?language=ar&session_token=&country=SA&access_token=sk.eyJ1Ijoid2FzYWx0bWFwcyIsImEiOiJjbGM2OXUzODkwMjhhM3BtZ2x4dmtvd21hIn0.uLcik68kLtKKCqKvpLzD6A'
- POST(Retrieve suggested item's more info)
curl --location -g --request POST 'https://api.mapbox.com/search/v1/retrieve?session_token=[GENERATED-UUID]&access_token=pk.eyJ1Ijoid2FzYWx0bWFwcyIsImEiOiJjbDlkdHhtOW8xbjVzM3dwOGFzcm0xbmI1In0.aKPN7qWIPGX8hbKcOV_hbA' \
--header 'Content-Type: application/json' \
--data-raw '{
"id": "GpLnHR-w8BMB2AxARJ1nZYvXueJQn4PQ1GKu3mT11_5uLytWHFBsI7LnCBhFmrtosuecy3HLMPRTbcte0bBJYqe4XmLO3DCCJoeqcrJwzBeK_n1Hrfq5zBS034KiwOObxR1Wmv4MTKFW0vanZjPlO3j9QOJZJLjrIaW2Olfdc91WmEAqB7yv2TxTpZFfOMmrvqhVWtRJyB_tgq5NzndtDxlG1wsXAl_1urUn0VsmEe3VpBkyOm6MnBZwUKWMq3RELeTduG4jG1zNElVvjjS_aiZfg_VXsfbhit5J4efCwiResxecDKrLlaDbLRuDGOeFOC8XCb5_eM1O35zZEi7U_HujRi_v5bMinyfvnQfo0kWJTIVmgvHyfUS5eyzOzdaaEWwoblfFfo4MxQA-j_wdFOMmsDvyHL9BwOaGufjaWuN-6gW0eZBqrY3tJnwfYgY9liRlUMdc8FxCuzg0D0QDCduFp8H2nUXI8ALZV2wIN510XgJAg3r80T85quTp80dBRyXvP4R7_9XG5mFXcflsRTeCZsjaRDBVC400ff-06rHPVBKtHtuIGqjWE7p9AEjf17RX9fwY8MFocA1JZrRrTDwHQFFBCV-wbcbUGL4s50BLn2jkkClPNr0-yiDt14AJg3JP0NDPJa73hjRtC2i5Jm74VqPy_XK632rgeMHKB8IDyabJjKPJvQk-EPE0LL3YgR-JH4wC4UCOMOxPciuBoZ4hxF3GChra-fiQRVF6M6c4N5r323922nyIYIv9sX1RS3c7DcnWRZ0KsXc5PWD-hd8ZR2uLN8nMVwwak2u0axjh2WzrUeD27Yk_5ZIhNxxWsH8VNNyVfMT5Ig2FT3_FYJj-Hb-KwSv629ohr1kEWeNWH4LhI_jmCAIzzleoVk3j7XrRKtUb8lUqWye4ah7f5GceHl4gANhPM2fdDMZDbO8tUOuepEWoO5BQRGJiChM4h-85cJ5JO7zDSzsaA1WwFQf9EyPdhEaJB8tN8UNAmpF4vtpM3HsvGmnv7AY63oLj0VkusigK-UEPvxu4_3bixk6PDCTwZXsJEpYB_TcXwKXmrPnKbrYmDqt9psvWG8SlziKs3YYyMIs5HoP1eVQpQGmR06YQ8hxw8O2XFQdRUKvptHYDiwuY03R2YGDspiYu1UD2fj7muraZNZsk-VWFjRfuztunsTe-vtuJtqdyilyXGpWgft9t14GXOl-F5HfnMqYP_tzlCW1CedCchrRG_WdDL0IWfxF_LhkK4BjSoh7o2-pb4gLxEJ-k0--xYRIxPZgpRZ9YrHdNi8hXYsPQFwv6x91nw7jSPAZXcwvgYb8VCOgJrca9D6BHzXAD1VXXKi-9h9LnYkUA1cGKQ1p_o4sQU2OLslOD3jgNTOVRzePfkvbqkjXeiIdWlzuz2o2fvdyaxym7jWR-1qiIFzeXIaCeT746pEmLBw=="
}'
- GET(Gives list of POIs)
curl --location --request GET 'https://api.mapbox.com/geocoding/v5/mapbox.places/fast food;college;university.json?type=poi&proximity=-74.70850,40.78375&access_token=pk.eyJ1IjoiZGVlcGFrMTIyMSIsImEiOiJjbDhiZXQ5cmEwcXhzM3FvNTFhNDNpNms3In0.x6FPXW7P3lIWTKPs6PMaJA'
- GET(Gives info about inputed text))
curl --location --request GET 'https://api.mapbox.com/geocoding/v5/mapbox.places/Los%20Angeles.json?access_token=pk.eyJ1Ijoid2FzYWx0bWFwcyIsImEiOiJjbDlkdHhtOW8xbjVzM3dwOGFzcm0xbmI1In0.aKPN7qWIPGX8hbKcOV_hbA'
- GET(Gives info about provided coordinates)
curl --location --request GET 'https://api.mapbox.com/search/v1/reverse/13.329048,52.51258?language=en&access_token=pk.eyJ1Ijoid2FzYWx0bWFwcyIsImEiOiJjbDlkdHhtOW8xbjVzM3dwOGFzcm0xbmI1In0.aKPN7qWIPGX8hbKcOV_hbA&country=SA'
Code:
Mapview.js
import MapboxGL, {Camera, PointAnnotation, MarkerView} from '@rnmapbox/maps';
import {MAP_BOX_ACCESS_TOKEN} from '../../utils/constants/constants';
import * as turf from '@turf/turf';
import SearchLocationInput from './SearchLocationInput';
MapboxGL.setAccessToken(MAP_BOX_ACCESS_TOKEN);
const ANNOTATION_SIZE = 30;
const MAP_VIEW = ({navigation}) => {
let _map = useRef(null);
let camera = useRef(null);
let pointAnnotation = useRef(null);
const [poiList, setpoiList] = useState([]);
const [currentPinCoordinate, setcurrentPinCoordinate] = useState([
46.6753, 24.7136,
]);
// const [currentSelectedPoi, setCurrentSelectedPoi] = useState({});
const [routeGeoJOSN, setrouteGeoJOSN] = useState();
const [centerOfLineString, setcenterOfLineString] = useState();
useEffect(() => {
if (currentPinCoordinate && currentPinCoordinate.length > 0) {
console.log('currentPinCoordinate', currentPinCoordinate);
}
}, [currentPinCoordinate]);
const defaultCamera = {
centerCoordinate: [46.6753, 24.7136],
zoomLevel: 15,
};
const onPressInterestSite = async name => {
let response = await fetch(
'https://api.mapbox.com/geocoding/v5/mapbox.places/mosque.json?' +
new URLSearchParams({
type: 'poi',
proximity: '46.6753,24.7136',
access_token: MAP_BOX_ACCESS_TOKEN,
limit: 10,
}),
);
let data = await response.json();
console.log('onPressInterestSite', data);
setpoiList(data);
};
const onSelectPoiFunc = async payload => {
console.log('poi:', payload);
let coords = payload?.center;
// setCurrentSelectedPoi(payload);
let response = await fetch(
`https://api.mapbox.com/directions/v5/mapbox/driving/${currentPinCoordinate[0]},${currentPinCoordinate[1]};${coords[0]},${coords[1]}?` +
new URLSearchParams({
geometries: 'geojson',
access_token: MAP_BOX_ACCESS_TOKEN,
}),
);
let data = await response.json();
let lineStringGeoJSON = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {},
geometry: data?.routes[0]?.geometry,
},
],
};
setrouteGeoJOSN(lineStringGeoJSON);
let allCoordinates = lineStringGeoJSON?.features[0]?.geometry?.coordinates;
console.log(
'onPressInterestSiteDirection',
data,
lineStringGeoJSON,
allCoordinates[Math.round(allCoordinates.length / 2)],
);
let featuresCenter = turf.points(allCoordinates);
let center = turf.center(featuresCenter);
setcenterOfLineString(center?.geometry?.coordinates);
};
const RouteLineString = () => (
<MapboxGL.ShapeSource id="routeLine" shape={routeGeoJOSN}>
<MapboxGL.LineLayer id="lines" style={styles.mapBox} />
</MapboxGL.ShapeSource>
);
const CustomCalloutView = ({message}) => {
return (
<View style={styles.callOutContainer}>
<View style={styles.callOutInner} />
<View style={[styles.triangle, styles.arrowDown]} />
</View>
);
};
const onDragEnd = payload => {
let centerCoordinate = payload?.geometry?.coordinates;
setcurrentPinCoordinate(centerCoordinate);
camera?.current?.setCamera({
centerCoordinate,
zoomLevel: defaultCamera?.zoomLevel,
animationDuration: 1000,
animationMode: 'flyTo',
});
};
const selectedItemResDropdown = payload => {
console.log('SELECTED_DROPDOWN_ITEM_RESPONSE', payload);
let centerCoordinate = payload?.geometry?.coordinates;
setcurrentPinCoordinate(centerCoordinate);
camera?.current?.setCamera({
centerCoordinate,
zoomLevel: defaultCamera?.zoomLevel,
animationDuration: 3000,
animationMode: 'flyTo',
});
};
return (
<View style={styles.page}>
<TouchableOpacity
style={styles.tempGoback}
onPress={() => navigation.goBack()}
/>
{/* REUSABLE MARKER SEARCH COMPONENT */}
<SearchLocationInput
textInputText={''}
selectedItemRes={res => selectedItemResDropdown(res)}
currentPinCoordinate={currentPinCoordinate}
/>
{/* REUSABLE MARKER SEARCH COMPONENT */}
<View style={styles.container}>
<MapboxGL.MapView
ref={_map}
style={styles.map}
styleURL={MapboxGL.StyleURL.Street}
localizeLabels={true}
attributionEnabled={false}
logoEnabled={false}>
<Camera ref={camera} defaultSettings={defaultCamera} />
<PointAnnotation
key={1}
id={'1'}
coordinate={currentPinCoordinate}
draggable
onDragEnd={onDragEnd}
ref={pointAnnotation}>
<View style={styles.annotationContainer}>
<Image
source={{uri: 'https://reactnative.dev/img/tiny_logo.png'}}
style={styles.imgStyle}
onLoad={() => pointAnnotation.current?.refresh()}
/>
</View>
</PointAnnotation>
{poiList?.features && poiList?.features.length > 0
? poiList?.features.map((value, index) => (
<MarkerView key={value.id} coordinate={value?.center}>
<Pressable onPress={() => onSelectPoiFunc(value)} key={index}>
<View style={styles.marker} />
</Pressable>
</MarkerView>
))
: null}
{routeGeoJOSN && <RouteLineString />}
{centerOfLineString && (
<MapboxGL.MarkerView
id="selectedFeatureMarkerView"
coordinate={centerOfLineString}>
<CustomCalloutView />
</MapboxGL.MarkerView>
)}
</MapboxGL.MapView>
</View>
<View style={styles.bottomContainer}>
<Button title={'SHOPPING'} onPress={onPressInterestSite} />
<Button title={'RESTAURANT'} onPress={onPressInterestSite} />
<Button title={'MOSQUE'} onPress={onPressInterestSite} />
<Button title={'HOSPITAL'} onPress={onPressInterestSite} />
</View>
</View>
);
};
export default MAP_VIEW;
const styles = StyleSheet.create({});
SearchLocationInput.js
import React, {useEffect, useState} from 'react';
import {
View,
Text,
FlatList,
TextInput,
StyleSheet,
TouchableOpacity,
} from 'react-native';
import {MAP_BOX_ACCESS_TOKEN} from '../../../utils/constants/constants';
import {isRTL} from '../../../i18n';
import {useFirstRender} from '../../newTabsGallery/galleryComponents/reusableHooks';
const SearchLocationInput = ({
textInputText = '',
selectedItemRes,
currentPinCoordinate = [],
}) => {
const [resultList, setresultList] = useState([]);
const [inputText, setinputText] = useState(textInputText);
const firstRender = useFirstRender();
useEffect(() => {
if (!firstRender) {
reverseGeocodingData();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentPinCoordinate]);
const reverseGeocodingData = async (bool = true) => {
// bool true = poi, bool false = region
let searchParams = new URLSearchParams({
access_token: MAP_BOX_ACCESS_TOKEN,
language: isRTL() ? 'ar' : 'en',
country: 'SA',
limit: 1,
// type: 'poi',
});
let response = await fetch(
bool
? `https://api.mapbox.com/geocoding/v5/mapbox.places/${currentPinCoordinate[0]},${currentPinCoordinate[1]}.json?` +
searchParams
: `https://api.mapbox.com/search/v1/reverse/${currentPinCoordinate[0]},${currentPinCoordinate[1]}?` +
searchParams,
);
let result = await response.json();
let resData = bool
? result?.features[0]?.text
: result?.features[0]?.properties?.feature_name;
console.log('reverseGeocodingData', resData);
setinputText(resData);
};
const searchItems = async text => {
try {
setinputText(text);
if (text.length > 2) {
let response = await fetch(
`https://api.mapbox.com/search/v1/suggest/${text}?` +
new URLSearchParams({
access_token: MAP_BOX_ACCESS_TOKEN,
session_token: '',
language: isRTL() ? 'ar' : 'en',
country: 'SA',
// types:
// 'country, region, prefecture, postcode, district, place, city, locality, oaza, neighborhood, chome, block, street, address',
}),
);
let result = await response.json();
setresultList(
result?.suggestions.length > 0 ? result?.suggestions : [],
);
} else {
setresultList([]);
}
} catch ({message}) {
setinputText('');
setresultList([]);
console.log('searchItemsSiteERROR', message);
}
};
const onPressListItem = async item => {
try {
let options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(item?.action?.body),
};
let response = await fetch(
'https://api.mapbox.com/search/v1/retrieve?' +
new URLSearchParams({
access_token: MAP_BOX_ACCESS_TOKEN,
session_token: '',
}),
options,
);
let result = await response.json();
selectedItemRes(result?.features[0]);
setinputText(result?.features[0]?.properties?.feature_name);
setresultList([]);
} catch ({message}) {
console.log('onPressListItemERROR', message);
}
};
const renderSeparator = () => {
return (
<View
style={{
height: 1,
width: '100%',
backgroundColor: '#CED0CE',
}}
/>
);
};
return (
<View
style={{
flex: 1,
width: '98%',
position: 'absolute',
top: 100,
zIndex: 1,
backgroundColor: 'white',
}}>
<TextInput
style={{height: 60, borderColor: '#000', borderWidth: 1}}
placeholder=" Type Here...Key word"
onChangeText={searchItems}
value={inputText}
/>
{inputText && (
<FlatList
data={resultList}
renderItem={({item}) => (
<TouchableOpacity onPress={() => onPressListItem(item)}>
<Text style={{padding: 10}}>{item?.feature_name} </Text>
</TouchableOpacity>
)}
keyExtractor={(item, index) => index + ''}
ItemSeparatorComponent={renderSeparator}
/>
)}
</View>
);
};
export default SearchLocationInput;
const styles = StyleSheet.create({});
Top comments (1)
Does this API is free for development?