Search code examples
javascriptreactjsmapboxgeojsonturfjs

Turn mapbox line into turf.js curved (bezier) line in React


I'm trying to find a way to turn the regular mapbox line into a bezier curve as provided by Turf.js

The snippets on there aren't particularly helpful - they have an addToMap variable but doesn't say what to do with it - and I can't seem to figure out how to add the line to the map in React.

This is how I draw the default/straight line currently:

const [route] = useState<FeatureCollection<LineString>>({
type: 'FeatureCollection',
features: [
  {
    type: 'Feature',
    geometry: {
      type: 'LineString',
      coordinates: [
        [originAirport.longitude, originAirport.latitude],
        [destinationAirport.longitude, destinationAirport.latitude],
      ],
    },
    properties: {},
  },
],

}); const [lineLayer] = useState({ id: 'route', source: 'route', type: 'line', paint: { 'line-width': 2, 'line-color': '#007cbf', }, });

Later on, in the return:

<Source
    id="map-line"
    type="geojson"
    data={{
      ...route,
      features: [
        {
          ...route.features[0],
          geometry: {
            ...route.features[0].geometry,
            coordinates: [
              [originAirport.longitude, originAirport.latitude],
              [destinationAirport.longitude, destinationAirport.latitude],
            ],
          },
        },
      ],
    }}
  >
    <Layer {...lineLayer} />
  </Source>

I tried wrapping the coordinates in the turf.bezierSpline fn, but that failed. Can't find another way to add it.

I'm using react-mapb-gl, but there isn't much out there on integrating it with turf.js. I also tried adding an extra source layer, like so:

const line = turf.lineString([
  [-76.091308, 18.427501],
  [-76.695556, 18.729501],
]);

const curved = turf.bezierSpline(line);

in the return:

<Source id="test" type="geojson" data={curved}>
  <Layer {...lineLayer} />
</Source>

Solution

  • For anyone coming back to this thread:

    The problem was in the way I passed data to Source. If you console log the data returned by curved, it doesn't return a whole FeatureCollection like I was storing in my route state variable; it just returns one feature. So the data should be passed into Source like so:

    <Source id="test" type="geojson" data={{ ...route, features: [curved] }}>
      <Layer {...lineLayer} />
    </Source>