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

Geolocate #5

Open
seddonm1 opened this issue Jan 15, 2017 · 15 comments
Open

Geolocate #5

seddonm1 opened this issue Jan 15, 2017 · 15 comments

Comments

@seddonm1
Copy link

Hi,
Have you worked out a method for listening to geolocate events so a GPS tracking dot could be added to the maps?

@cammanderson
Copy link
Contributor

We are going to be working on this internally over the next fortnight. Hopefully I can post some progress as examples. :-) Initially, I imagine you'd have to listen to the geolocation events separately and update your map style source, and have a corresponding layer style to match.

@seddonm1
Copy link
Author

Great. In Sydney so on same timezone if you need testing help. Good work on library and your site looks good 👍

@cammanderson
Copy link
Contributor

cammanderson commented Jan 17, 2017

Hi @seddonm1,

Just sharing a quick gist for binding a map center to the geolocation of a user on mount. https://gist.github.com/cammanderson/5e4a32d4b19cf2413aeee5d88a3b3f58

This is just early on for you in case you want to progress something quickly.

Depending on your use case, you could have it so that onClick the geolocation event is called once off to update the map position; https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/getCurrentPosition

I am assuming that you have a custom map style where you are in control of the source and layers? Instead of supplying your map a mapStyle URL? You'll need that to be able to modify the style dynamically. You can load it in using Axios or similar in a middleware or using webpack/json-loader approach that gives you access to the style as an object where you could possibly mutate it.

The next step to have it show up as a dot would be to have a map style source that is a type 'geoJson' with a feature point that is updated with the lnglat position obtained by the watch position.

To setup a geoJSON source, there is this documentation available
https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson

To watch the users position as it updates, you can use watchPosition and then have it update your above geoJSON source
https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/watchPosition

You could then style the source with a layer that has a symbols for the dot as you want;
https://www.mapbox.com/mapbox-gl-style-spec/#layers-symbol

I'll do my best to share more example code to implement your original request.

Cheers
Cameron

@seddonm1
Copy link
Author

Thanks Cameron.
Sorry for the delay I have been building backend stuff too.

Yes we will use a combination of layers so I will try your code. I was thinking a geolocate overlay would be very nice. I just need to get my head around the mapboxgl js api as I have done a lot of leafletjs.

@seddonm1
Copy link
Author

seddonm1 commented Jan 19, 2017

Great! works well.

Can you please bump the mapboxgl version to 0.29 so we get access to a few extra 'circle' rendering options (circle-stroke-width and circle-stroke-color). I will see if i can work out how to convert the geolocate accuracy attribute to circle-radius to do the confidence ring like other maps.

{
  'id': 'geolocate_point',
  'type': 'circle',
  'source': "geolocate",
  'paint': {
    "circle-radius": 6.5,
    "circle-color": "#4285F4",
    "circle-stroke-width": 1,
    "circle-stroke-color": "#fff"
  }
}

@cammanderson
Copy link
Contributor

OK yes, I will do a version bump. Give me until Monday if that is alright.

@cammanderson
Copy link
Contributor

Hi @seddonm1,

I've pushed the changes to version as a bump to master, but our tests aren't passing. We are getting a failed to invert matrix error. I will need to investigate that. From a browser based test though, it appears to be working fine. Maybe the test needs to be updated.

I'll continue to investigate on the weekend.

Speak soon
Cam

@cammanderson
Copy link
Contributor

I'm going to move this into a branch and revert in master; that was a wrong to push to master. I'll create the branch for the next bump.

@cammanderson
Copy link
Contributor

OK PR ready for pull and version bump.

@cammanderson
Copy link
Contributor

OK @seddonm1 - released v0.4.0 with mapbox-gl-js 0.31.0 support. Let me know if there are any issues.

@seddonm1
Copy link
Author

great. will test.

also, you should probably add the accuracy attribute to your state so we can use it to show the confidence circle (once i get the maths sorted):

  _updatePosition(position) {
    this.setState({
      target: {
        ...this.state.target,
        center: [position.coords.longitude, position.coords.latitude],
        accuracy: position.coords.accuracy
      },
    });
  }

@seddonm1
Copy link
Author

Hi,
Just an update. My conversion from geolocate accuracy to meters (to show the geolocate confidence circle) is using this formula. I think it's correct but a bit hard to find much clarity. It is working nicely:

let accuracy = viewport ? 1/(40075016.686 * Math.abs(Math.cos(target.center[1] * 180/Math.PI)) / Math.pow(2, viewport.zoom+8)) * target.accuracy : 0

@cammanderson
Copy link
Contributor

Great progress @seddonm1! We are progressing slowly on our release, and hopefully will have something ready in the next couple of days. I'm keen to try out your accuracy formula! Did you by chance have a gif of your progress in action? (they always create a bit of wow!)

@seddonm1
Copy link
Author

Hi Cam.
Nothing very exciting so no git at the moment. But here are my layer defs. Basically the flow is:

  1. enable geolocate and register _updatePosition callback
  2. _updatePosition sets target.accuracy = position.coords.accuracy
  3. calculate pixels: let accuracy = viewport ? 1/(40075016.686 * Math.abs(Math.cos(target.center[1] * 180/Math.PI)) / Math.pow(2, viewport.zoom+8)) * target.accuracy : 0
  4. render block includes a style.layers[style.layers.findIndex(layer => layer.id === 'geolocate_confidence')].paint["circle-radius"] = accuracy

Sources:

      "geolocate": {
        "type": "geojson",
        "data": {
          "type": "Feature",
          "geometry": {
            "type": "Point",
            "coordinates": [0,0]
          },
        }
      }

Layers:

    {
        "id": "geolocate_confidence",
        "type": "circle",
        "source": "geolocate",
        "layout": {
            "visibility": "none",
        },
        "paint": {
          "circle-radius": 0,
          "circle-color": "#4285F4",
          "circle-opacity": 0.3
        }
    },
    {
        "id": "geolocate",
        "type": "circle",
        "source": "geolocate",
        "layout": {
            "visibility": "none",
        },
        "paint": {
          "circle-radius": 7.5,
          "circle-color": "#4285F4",
          "circle-opacity": 1,
          "circle-stroke-width": 2.5,
          "circle-stroke-color": "#FFFFFF",
          "circle-stroke-opacity": 1,
        }
    },

@seddonm1
Copy link
Author

I have also had great success with the custom d3 overlays (which I thought was going to be difficult but with Uber's viewport-mercator-project project they have done all the hard work!

https://github.com/uber/react-map-gl/blob/master/src/overlays/svg.react.js

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

2 participants