Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to draw a navigation line on a mapbox map in react-native?

I am trying to get navigation directions using mapbox-sdk for react-native from npm package:

"@mapbox/mapbox-sdk": "^0.11.0"

And for rendering the directions returned by mapbox-sdk I am using the below npm package:

"@react-native-mapbox-gl/maps": "^8.1.0-rc.8",

Code I am using for retrieving directions:

import MapboxGL from '@react-native-mapbox-gl/maps'
// Mapbox SDK related package
import MapboxDirectionsFactory from '@mapbox/mapbox-sdk/services/directions'
import { lineString as makeLineString } from '@turf/helpers'
import GeoLocationService from '../../services/geolocation/GeoLocationService';
import GeoLocationCore from '@react-native-community/geolocation'

const accessToken = "ACESS_TOKEN_FROM_MAPBOX_API_DASHBOARD"
const directionsClient = MapboxDirectionsFactory({accessToken})


  constructor(props) {
    super(props);
    this.state = {
        longitude: 0,
        latitude: 0,
        orderLongitude: 0,
        orderLatitude: 0,
        route: null,
    };
  }

async componentDidMount() {
      
      const {route} = this.props

      // Lets say route.params contains the below object:
      // { "longitude": "33.981982", "latitude": "-6.851599"}
      console.log("Params from other screen: ", route.params)

      MapboxGL.setAccessToken(accessToken)
      MapboxGL.setConnected(true);
      MapboxGL.setTelemetryEnabled(true);
      const permission = await MapboxGL.requestAndroidLocationPermissions();

      let latitude, longitude;
      if(Platform.OS == "android") {
          GeoLocationService.requestLocationPermission().then(() => {
            GeoLocationCore.getCurrentPosition(
                info => {
                    const { coords } = info
    
                    latitude = coords.latitude
                    longitude = coords.longitude
                    
                    //this.setState({longitude: coords.longitude, latitude: coords.latitude})
                    this.setState({longitude: -6.873795, latitude: 33.990777, orderLongitude: route.params.longitude, orderLatitude: route.params.latitude})
                    console.log("your lon: ", longitude)
                    console.log("your lat", latitude)
                    this.getDirections([-6.873795, 33.990777], [route.params.longitude, route.params.latitude])

                },
                error => console.log(error),
                {
                    enableHighAccuracy: false,
                    //timeout: 2000,
                    maximumAge: 3600000
                }
            )
        })
      }
  }

  getDirections = async (startLoc, destLoc) => {
      const reqOptions = {
        waypoints: [
          {coordinates: startLoc},
          {coordinates: destLoc},
        ],
        profile: 'driving',
        geometries: 'geojson',
      };
      const res = await directionsClient.getDirections(reqOptions).send()
      //const route = makeLineString(res.body.routes[0].geometry.coordinates)
      const route = makeLineString(res.body.routes[0].geometry.coordinates)
      console.log("Route: ", JSON.stringify(route))
      this.setState({route: route})
      
  }

Code I am using for rendering road directions fetched by mapbox-sdk:

  renderRoadDirections = () => {
    const { route } = this.state
    return route ? (
      <MapboxGL.ShapeSource id="routeSource" shape={route.geometry}>
        <MapboxGL.LineLayer id="routeFill" aboveLayerID="customerAnnotation" style={{lineColor: "#ff8109", lineWidth: 3.2, lineCap: MapboxGL.LineJoin.Round, lineOpacity: 1.84}} />
      </MapboxGL.ShapeSource>
    ) : null;
  };

Code I am using for rendering map and directions:

render() {
   return (
       <View style={{ flex: 1 }}>
         <MapboxGL.MapView
                ref={(c) => this._map = c}
                style={{flex: 1, zIndex: -10}}
                styleURL={MapboxGL.StyleURL.Street}
                zoomLevel={10}
                showUserLocation={true}
                userTrackingMode={1}
                centerCoordinate={[this.state.longitude, this.state.latitude]}
                logoEnabled={true}
                >
                    {this.renderRoadDirections()}
            <MapboxGL.Camera
                zoomLevel={10}
                centerCoordinate={[this.state.longitude, this.state.latitude]}
                animationMode="flyTo"
                animationDuration={1200}
            />
        </MapboxGL.MapView>
       </View>
    )
}

Now when I try to render the GeoJson retreived the road directions line not showing on map, so I thought maybe something wrong with my GeoJson and tested it from here but it looks fine:

https://geojsonlint.com/

GeoJson that I tested and looks okay:

{"type":"Feature","properties":{},"geometry":{"type":"LineString","coordinates":[[-6.880611,33.9916],[-6.882194,33.990166],[-6.882439,33.99015],[-6.882492,33.990028],[-6.882405,33.98991],[-6.878006,33.990299],[-6.87153,33.990978],[-6.871386,33.990925],[-6.871235,33.991016],[-6.869793,33.991165],[-6.870523,33.990292]]}}

Example of what I am trying to achieve:

enter image description here

What could be wrong in my code that makes road directions line not showing on map?

like image 973
0x01Brain Avatar asked Oct 26 '20 15:10

0x01Brain


People also ask

How do I draw a line in Mapbox?

The preferred way to draw lines within Mapbox GL JS is to express the lines as GeoJSON and add them to the map as a GeoJSONSource / line layer pair. You might find this example of drawing a GeoJSON line and this example of drawing a great arc line helpful.

Does Mapbox work with React Native?

The Maps SDK for React Native is a community-maintained React Native library that provides reusable JavaScript components for integrating Mapbox maps into iOS and Android apps. The Maps SDK for React Native is maintained by community volunteers.

How do I add a polyline in Mapbox?

The map provided by Mapbox doesn't have a Polyline component by default but we can leverage on other components that gives us the same result as what we get from Google Maps Polylines. To add a polyline on our map, we would be using the ShapeSource and LineLayer component provided by Mapbox.

How do I show directions in Mapbox?

Use the mapbox-gl-directions plugin to show results from the Mapbox Directions API. Click the map to add an origin and destination, and use the toggle to switch among the available routing profiles. The Mapbox Directions API is billed per request.


1 Answers

Found what was causing the <LineLayer/> not showing on map, removing the the attribute aboveLayerID from the following line:

<MapboxGL.LineLayer id="routeFill" aboveLayerID="customerAnnotation" style={{lineColor: "#ff8109", lineWidth: 3.2, lineCap: MapboxGL.LineJoin.Round, lineOpacity: 1.84}} /> 

So it becomes:

<MapboxGL.LineLayer id="routeFill" style={{lineColor: "#ff8109", lineWidth: 3.2, lineCap: MapboxGL.LineJoin.Round, lineOpacity: 1.84}} />

Result:

enter image description here

like image 150
0x01Brain Avatar answered Oct 12 '22 23:10

0x01Brain