12

I'm trying to add a GeoJSON line to show car direction between a point A and a point B ( like they have in the official documentation of mapbox-gl-js (https://www.mapbox.com/mapbox-gl-js/example/geojson-line/)

But the docs of react-map-gl doesn't talk about that at all.

How can I achieve something similar to this using https://uber.github.io/react-map-gl/#/Documentation/introduction/introduction :

here's my code so far :

class MapPage extends Component {
  constructor(props) {
    super(props);
     this.state = {
      viewport: {
       latitude: 38.63738602787579,
       longitude: -121.23576311149986,
       zoom: 6.8,
       bearing: 0,
       pitch: 0,
       dragPan: true,
       width: 600, 
       height: 600 
     }
    };
   }

render() {
  const { viewport } = this.state;

  return (
    <ReactMapGL
      {...viewport}
      mapboxApiAccessToken={MAPBOX_TOKEN}
      onViewportChange={newViewport => {
        this.setState({ viewport: newViewport });
      }}
    />
  );
 }
}

screen shot 2017-12-20 at 5 55 10 pm

wentjun
  • 40,384
  • 10
  • 95
  • 107
AziCode
  • 2,510
  • 6
  • 27
  • 53

3 Answers3

10

You can get the mapbox-gl map object once the component mounts, then you can work with it directly. Try something like this:

class MapPage extends Component {
      constructor(props) {
        super(props);
         this.state = {
          viewport: {
           latitude: 38.63738602787579,
           longitude: -121.23576311149986,
           zoom: 6.8,
           bearing: 0,
           pitch: 0,
           dragPan: true,
           width: 600, 
           height: 600 
         }
        };
       }
    componentDidMount(){
      const map = this.reactMap.getMap();
      map.on('load', () => {
       //add the GeoJSON layer here
       map.addLayer({...})
      })
    }

    render() {
      const { viewport } = this.state;

      return (
        <ReactMapGL
          ref={(reactMap) => this.reactMap = reactMap} />
          {...viewport}
          mapboxApiAccessToken={MAPBOX_TOKEN}
          onViewportChange={newViewport => {
            this.setState({ viewport: newViewport });
          }}
        />
      );
     }
    }

React Refs: https://reactjs.org/docs/refs-and-the-dom.html

GetMap(): https://uber.github.io/react-map-gl/#/Documentation/api-reference/static-map?section=methods

Kristofor Carle
  • 1,405
  • 12
  • 14
5

Applicable for those who are using react-map-gl Version 5.0 onwards

As of October 2019, react-map-gl supports Layer and Source components, which is meant to allow developers to render Mapbox layers on the Mapbox canvas without the need to call getMap() to expose the underlying native Mapbox API.

You may refer to the original Mapbox Source and Layer documentations for the full specifications for the valid values for the Layer and Source props.

This is how the Source and Layer components can be used together with the code you have provided to generatea GeoJSON line on your map.

class MapPage extends Component {
  constructor(props) {
    super(props);
     this.state = {
      viewport: {
       latitude: 38.63738602787579,
       longitude: -121.23576311149986,
       zoom: 6.8,
       bearing: 0,
       pitch: 0,
       dragPan: true,
       width: 600, 
       height: 600 
     }
    };
   }

render() {
  const { viewport } = this.state;

  return (
    <ReactMapGL
      {...viewport}
      mapboxApiAccessToken={MAPBOX_TOKEN}
      onViewportChange={newViewport => {
        this.setState({ viewport: newViewport });
      }}
    >
      <Source id='polylineLayer' type='geojson' data={polylineGeoJSON}>
        <Layer
          id='lineLayer'
          type='line'
          source='my-data'
          layout={{
           'line-join': 'round',
           'line-cap': 'round',
          }}
          paint={{
           'line-color': 'rgba(3, 170, 238, 0.5)',
            'line-width': 5,
          }}
        />
      </Source>
    </ReactMapGL>
  );
 }
}
wentjun
  • 40,384
  • 10
  • 95
  • 107
  • Hello I am trying to run your code, would you mind give one example of polylineGeoJSON ? – Sean Liu Jun 04 '21 at 19:42
  • Can you provide an exemple of what look like polylineGeoJSON and source='my-data' please ? – crg Jun 17 '21 at 10:17
  • TypeScript definition of `polylineGeoJSON`: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/a4f1b378c10faf3a258d44f498c9412135290847/types/geojson/index.d.ts#L172-L175 – Richie Bendall Oct 21 '21 at 09:49
0
nice job.
now try this.
import React, { Component } from 'react';
import ReactMapGL, {
  Marker,
  FullscreenControl,
  GeolocateControl,
  Source,
  Layer,
  SVGOverlay,
  HTMLOverlay,
  NavigationControl,
  LinearInterpolator,
  CanvasOverlay,
  Popup
} from 'react-map-gl';
const geojson = {
  type: 'FeatureCollection',
  features: [
    { type: 'Feature', geometry: { type: 'Point', coordinates: [73.05625599999999, 33.644543999999996] } }
  ]
};

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      markerLat: 33.644543999999996,
      markerlng: 73.05625599999999,
      showPopup: true,
      viewport: {
        width: window.innerWidth,
        height: window.innerHeight,
        latitude: 41.8662,
        longitude: -87.61694,
        zoom: 15.99,
        pitch: 40,
        bearing: 20,
        antialias: true
      }
    };
    this.re = React.createRef();
  }

  componentDidMount(){
   // window.addEventListener("resize", this.resize.bind(this));
    const map = this.reactMap.getMap();
   // console.log('map object',map.on)
    map.on('load', function() {

     //add the GeoJSON layer here
    map.addLayer({
      'id': 'room-extrusion',
'type': 'fill-extrusion',
'source': {
// GeoJSON Data source used in vector tiles, documented at
// https://gist.github.com/ryanbaumann/a7d970386ce59d11c16278b90dde094d
'type': 'geojson',
'data': 'https://docs.mapbox.com/mapbox-gl-js/assets/indoor-3d-map.geojson'
},
'paint': {
// See the Mapbox Style Specification for details on data expressions.
// https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions

// Get the fill-extrusion-color from the source 'color' property.
'fill-extrusion-color': ['get', 'color'],

// Get fill-extrusion-height from the source 'height' property.
'fill-extrusion-height': ['get', 'height'],

// Get fill-extrusion-base from the source 'base_height' property.
'fill-extrusion-base': ['get', 'base_height'],

// Make extrusions slightly opaque for see through indoor walls.
'fill-extrusion-opacity': 1
}
    })
    })
  }
  resize() {
    //alert(window.innerWidth);
    this.setState({
      viewport: {
        width: window.innerWidth,
        height: window.innerHeight
      }
    }, () => {
      //  console.log(this.state.viewport.width)
    });
  }

  render() {
    var markerLat = this.state.markerLat;
    var markerlng = this.state.markerlng
    return (
      <div>
        <ReactMapGL
          {...this.state.viewport}
          ref={(reactMap) => this.reactMap = reactMap}
          // transitionDuration={1000}
          //transitionInterpolator={new LinearInterpolator()}
          mapboxApiAccessToken={'pk.eyJ1IjoiemVlc2hhbjU1NzI2MTUiLCJhIjoiY2syaWoyNDAxMGdvbTNscGJobDZwcHAxMCJ9.tcB8DX8W-7XMY7nzX9ilvw'}
          onViewportChange={(viewport) => {
            // console.log('viewprt' , viewport)
            this.setState({
              viewport: viewport
            }, () => {
              // console.log(this.state.viewport.width)
            });
          }}
        >
          <div style={{ position: 'absolute', right: 10, top: 10 }}>
            <FullscreenControl container={document.querySelector('body')} />
          </div>
          {/*  <GeolocateControl 
          positionOptions={{enableHighAccuracy: true}}
          trackUserLocation={true}
          showUserLocation={true}
        />
  <Marker 
        latitude={this.state.markerLat} 
        longitude={this.state.markerlng} 
        offsetLeft={-20} offsetTop={-10}
        draggable ={true}

      onDragEnd={(x)=>{
        console.log('event ',x)
        this.setState({
          markerLat:x.lngLat[0],
          markerlng:x.lngLat[1]
        })
      }}
        >
  <p style={{
    background:'#000',
    fontSize:20,
    padding:5,
    alignSelf:'center',
    fontWeight:'bold',
    borderRadius:'50%',
    lineHeight:.5
  }}><span>&nbsp;</span></p>
        </Marker>

        {this.state.showPopup && <Popup
          latitude={this.state.markerLat}
          longitude={this.state.markerlng}
          closeButton={true}
          closeOnClick={false}
          onClose={() => this.setState({showPopup: false})}
          anchor="bottom"
          tipSize={10} >
          <div>You are here</div>
        </Popup>*/}


          <div style={{ position: 'absolute', bottom: 30 }}>
            <NavigationControl />
          </div>
        </ReactMapGL>
      </div>
    );
  }
}