Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to display routes? #591

Closed
sachinshettigar opened this issue Sep 12, 2018 · 15 comments
Closed

Is it possible to display routes? #591

sachinshettigar opened this issue Sep 12, 2018 · 15 comments

Comments

@sachinshettigar
Copy link

I want to use Mapbox for one of my projects and was thinking of using this library to use it in react.
I want a feature where i can display routes with multiple stops along the routes. I see that mapbox has a directions API to get direction info and layers API to display the route for this purpose. I don't see any such thing in here.

Can we display routes using this library. If yes how? A small example would be really helpful.

@GunnarSturla
Copy link

GunnarSturla commented Sep 14, 2018

I'm having the same issue on my end, and from what I gather, there are three ways do draw lines/routes using this library.

First, and probably the easiest is using deck.gl's LineLayer. Deck.gl is a companion library of this one, they're both managed by Uber, and deck.gl is great to do all sorts of data visualizations on top of your maps. If all we need is to draw a line, however, it would probably bloat the bundle.

The second way is to add a GeoJSON layer to our mapStyle. You can see how it's done in the GeoJSON example. This is the way I'm currently doing it, but I find that working with the mapStyle and GeoJSON is neither easy nor readable. I would also like to have an easier way to use React's composition model, so I could have my line/route components as children of ReactMapGL, similar to how the marker control works.

The last way I've found is to create a custom overlay. This is probably the way I would like to go, but the documentation around it isn't very extensive. I found a folder with various overlay examples, but none of them make lines (as far as I could tell). The draggable points overlay might be the place to start, but I haven't gotten that far.

My dream scenario would be to have a line component that you could place inside the ReactMapGl component, just like the Marker and like react-leaflet's PolyLine works.

<ReactMapGL latitude={64.14} longitude={-20.22} zoom={8}>
  <PloyLine positions={[
    [-21.81884765625, 64.1297836764257],
    [-19.79736328125, 64.1585310519412]]}
  />
</ReactMapGL>

I'm not really happy with my solution to add the GeoJSON to the mapStyle so I plan on redoing it. My question to the maintainers is; would you accept a pr that adds a PolyLine component, similar to the Marker component, or should I create a custom overlay instead?

@secretwpn
Copy link

One approach, as mentioned above already, would be to go with a custom overlay. I've used the ScatterOverlay example to create my own PolylineOverlay

import React, { PureComponent } from 'react'
import { CanvasOverlay } from 'react-map-gl'

export default class PolylineOverlay extends PureComponent {
  _redraw ({ width, height, ctx, isDragging, project, unproject }) {
    const { points, color = 'red', lineWidth = 2, renderWhileDragging = true } = this.props
    ctx.clearRect(0, 0, width, height)
    ctx.globalCompositeOperation = 'lighter'

    if ((renderWhileDragging || !isDragging) && points) {
      ctx.lineWidth = lineWidth
      ctx.strokeStyle = color
      ctx.beginPath()
      points.forEach(point => {
        const pixel = project([point[0], point[1]])
        ctx.lineTo(pixel[0], pixel[1])
      })
      ctx.stroke()
    }
  }

  render () {
    return <CanvasOverlay redraw={this._redraw.bind(this)} />
  }
}

and then use it as follows

// points is an array of [[lat, lon], [lat, lon], ...]
<ReactMapGL ...>
  <PolylineOverlay points={points} />
</ReactMapGL>

This works quite well for my application

@YIPG
Copy link

YIPG commented Jan 18, 2019

@GunnarSturla
Really helpful!!
I also tried to create GeoJSON to add the line layer too. My process is like

  1. Get GeoJSON of the route by API here
{
  "routes": [
    {
      "geometry": {
        "coordinates": [
          [
            -73.98891,
            40.733122
          ],
          [
            -73.994118,
            40.735313
          ],
          [
            -73.996976,
            40.731414
          ],
          [
            -74.000066,
            40.732929
          ],
          [
            -74.00001,
            40.733004
          ]
        ],
        "type": "LineString"
      },
      "legs": [
        {
          "summary": "",
          "weight": 582.4,
          "duration": 380.6,
          "steps": [],
          "distance": 1317.9
        }
      ],
      "weight_name": "routability",
      "weight": 582.4,
      "duration": 380.6,
      "distance": 1317.9
    }
  ],
  "waypoints": [
    {
      "distance": 15.535684098115707,
      "name": "East 13th Street",
      "location": [
        -73.98891,
        40.733122
      ]
    },
    {
      "distance": 0.9545121434133703,
      "name": "6th Avenue",
      "location": [
        -74.00001,
        40.733004
      ]
    }
  ],
  "code": "Ok"
}
  1. Checked the Animating GeoJSON example. Then I realized that the GeoJSON format in the mapbox-gl or react-map-gl is quite different from the one I got above. Then I changed the above one to the below one.
"sources": {
        "route": {
            "type": "geojson",
            "data": {
                "type": "LineString",
                "coordinates": [
                    [-122.48369693756104, 37.83381888486939],
                    [-122.48348236083984, 37.83317489144141],
                    [-122.48339653015138, 37.83270036637107],
                ]
            }
        }
    },

"layers": [
        {
            "id": "route",
            "type": "line",
            "source": "route",
            "layout": {
                "line-join": "round",
                "line-cap": "round"
            },
            "paint": {
                "line-color": "#f06292",
                "line-width": 15
            }
        },
]

But sadly, it didn't work in my application. (I mean the routing path doesn't appear in a map.)

  1. I actually don't wanna give a try to Overlay something because it seems very relevant to D3.js and looks complicated.

I'm gonna work on Deck.gl's line layer or change to the Google Map. If there are the people well-informed of GeoJSON, please teach me how to show the line.

ps:
I found how to use mapbox-gl's instance. link
Then, follow this ref
related #429

@GunnarSturla
Copy link

@YIPG: I don't think the object you're using is correct. I'm not really an expert in GeoJSON but I've found geojson.io to be very helpful in visualizing my code.

I built the line you're trying to draw there and got this:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "stroke": "#f06292",
        "stroke-width": 15,
        "stroke-opacity": 1,
        "line-join": "round",
        "line-cap": "round"
      },
      "geometry": {
        "type": "LineString",
        "coordinates": [
                    [-122.48369693756104, 37.83381888486939],
                    [-122.48348236083984, 37.83317489144141],
                    [-122.48339653015138, 37.83270036637107]
        ]
      }
    }
  ]
}

Try seeing if that works, but did you try @secretwpn's overlay, it looks very promising?

@YIPG
Copy link

YIPG commented Jan 20, 2019

@GunnarSturla Thank you for your reply. I stuck with GeoJSON. I tried @secretwpn's polylineoverlay and it's totally working well! (And of course, your way is correctly working)

@DiwasSubedi
Copy link

Does any one has a working example which uses map box routes api and plot routes from the response on map ?

@jakeols
Copy link

jakeols commented Nov 9, 2019

Hey @DiwasSubedi , I'm not sure if this is what you're looking for, but here's an example of how I did it recently as a gist here. I didn't end up going with this library, but the concept is essentially the same.

@sharpar
Copy link

sharpar commented May 14, 2020

// points is an array of [[lat, lon], [lat, lon], ...]
<ReactMapGL ...>
  <PolylineOverlay points={points} />
</ReactMapGL>

Just in case anyone is trying and it isn't working, the format of the array should have the longitude first, then the latitude. So [[lon, lat], [lon, lat], ...].

project in CanvasOverlay expects the longitude first - https://github.com/visgl/react-map-gl/blob/master/docs/api-reference/canvas-overlay.md

@secretwpn thanks for your help!

@ariel262626
Copy link

Any updated solution? Can someone post a full example of draw simple polylines on the react-map-gl?

@sharpar
Copy link

sharpar commented Oct 25, 2020

@ariel262626 you could try using DeckGL and PathLayer: https://deck.gl/docs/api-reference/layers/path-layer

I tried using the custom overlay and got it working, but it was performing too slow when I had a lot of routes, so I switched to DeckGL. This medium post was helpful: https://medium.com/@sashakayola/map-layering-using-mapbox-gl-js-deck-gl-react-ba0ece89aaef

@AlfieFeldspar
Copy link

I think I'm too new at this stuff, but in the deck tutorial, they say "I specified an array of coordinates to form my path from point A to point B. Add in whatever data is appropriate for your particular overlay." The data I received from the Optimization API is not an array of coords - it delivers a mysterious "geometry" string. Anyone have experience with this?

@ariel262626
Copy link

ariel262626 commented Nov 1, 2020

I think I'm too new at this stuff, but in the deck tutorial, they say "I specified an array of coordinates to form my path from point A to point B. Add in whatever data is appropriate for your particular overlay." The data I received from the Optimization API is not an array of coords - it delivers a mysterious "geometry" string. Anyone have experience with this?

Yep, you can use the geometry as the data of the GeoJsonLayer:

 const layer = new GeoJsonLayer({
   id: 'geojson-layer',
   data: getGeometry(),
   pickable: true,
   stroked: false,
   filled: true,
   extruded: true,
   lineWidthScale: 20,
   lineWidthMinPixels: 2,
   getFillColor: [160, 160, 180, 200],
   getLineColor: d => colorToRGBArray(d.properties.color),
   getRadius: 100,
   getLineWidth: 1,
   getElevation: 30
 });

And then pass it to your DeckGL layers prop.

Check the docs here: https://deck.gl/docs/api-reference/layers/geojson-layer

@AlfieFeldspar
Copy link

AlfieFeldspar commented Nov 1, 2020 via email

@mathjp
Copy link

mathjp commented Feb 27, 2021

I am having an issue with routes, currently, it's going out of routes. I am using ScatterOverlay example to show the routes but whenever I zoom in few routes are going out of roads
image

@nonoumasy
Copy link

I was able to use the suggested canvas overlay to draw lines in between my location data.
I used the PolylineOverlay code above
and then just customized the ctx stuff. Would have like to have used arcTo or bezierTo, but they were complicated. lineTo was simple.

Screen Shot 2021-03-22 at 3 52 15 AM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests