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

Add vectorTileLayer events API to access underlying data #101

Open
jwasilgeo opened this issue Aug 9, 2021 · 1 comment
Open

Add vectorTileLayer events API to access underlying data #101

jwasilgeo opened this issue Aug 9, 2021 · 1 comment

Comments

@jwasilgeo
Copy link
Contributor

jwasilgeo commented Aug 9, 2021

We can gain access to the underlying data attributes rendered by mapbox-gl-js. The purpose of this enhancement is to define the API we create around L.esri.Vector.vectorTileLayer to enable it.

For example, here is a rough prototype code snippet of how this actually could work in our MapBoxGLLayer.js.

// this._map is the "outer" LeafletJS map instance

// this._glMap is a mapbox-gl-js map instance,
// which is the workhorse under the hood of esri-leaflet-vector

// 1. wire up a LeafletJS map click event callback
// 2. and pass the clicked coords to this._glMap.queryRenderedFeatures()
this._map.on('click', (e) => {
  // https://docs.mapbox.com/mapbox-gl-js/api/map/#map#queryrenderedfeatures
  const features = this._glMap.queryRenderedFeatures([e.latlng.lng, e.latlng.lat]);
  console.log(features);
});

With that in mind, I'd like help in defining what the API of L.esri.Vector.vectorTileLayer would look like.

  1. Idea: First investigate what happens when we try out some of the available methods on Leaflet's Layer, since vectorTileLayer directly inherits from that class. https://leafletjs.com/reference-1.7.1.html#layer

    For example, what does the following do and does it provide any useful information? How would we design an API that internally deals with the mapbox-gl-js map instance and returns any clicked features?

    myVectorTileLayer.on('click', (e) => console.log(e));
  2. Idea: Do we allow developers to attach/detach their own event handlers, and we just help return the feature data provided by this._glMap.queryRenderedFeatures()? This would be similar to esri-leaflet's FeatureLayer events

    ... L.esri.FeatureLayer also fires the following MouseEvents click, dblclick, mouseover, mouseout, mousemove, and contextmenu and the following the PopupEvents popupopen and popupclose

  3. Idea: Do we provide other instance methods such as bindPopup similar to esri-leaflet's DynamicMapLayer?

The 2nd idea sounds like a straightforward and incremental enhancement that would provide flexibility to developers. The 3rd--bindPopup--seems like a nice UI convenience but is quite specific in scope and Leaflet devs can still define a popup themselves on an interaction event.

@patrickarlt @gavinr @dhatcher

@jwasilgeo jwasilgeo changed the title Provide API to access underlying data Define vectorTileLayer API to access underlying data Aug 9, 2021
@jwasilgeo jwasilgeo changed the title Define vectorTileLayer API to access underlying data Add vectorTileLayer API to access underlying data Aug 9, 2021
@jwasilgeo
Copy link
Contributor Author

jwasilgeo commented Nov 8, 2021

This is a good starting place for what works today, as an example of what a developer can do today in their own consumer code to gain access to the mapbox-gl-js instance and call other methods, such as queryRenderedFeatures.

Ideally we'd still find a middle path where a consumer-dev would just wire up a simple click handler (or mousemove, or other documented user interactions available in LeafletJS) on their own VTL layer instance and we take care of things like: the overhead of communicating between LeafletJS and mapbox-gl-js, cleanly turning on and off their event handlers, etc.

I just pushed a new draft sample page in branch 101-click-handler to start investigating what our final API might look like.

const layer = L.esri.Vector.vectorTileLayer(... ... ...);

// EARLY PROTOTYPE PROOF-OF-CONCEPT:
// We can wire up a LeafletJS Map click hander (or mousemove, etc.),
// and then pass through the event.latlng info to the mapbox-gl-js instance, currently deeper down our VTL.
// There we have access to the `queryRenderedFeatures` method which gives us the client-side GeoJSON feature info we want.

map.on("click", (e) => {
  // https://docs.mapbox.com/mapbox-gl-js/api/map/#map#queryrenderedfeatures
  
  // A: example of passing in the clicked location
  // const features = layer._mapboxGL._glMap.queryRenderedFeatures([e.latlng.lng, e.latlng.lat]);

  // B: example of passing in a simple bbox extent around our clicked location
  // const features = layer._mapboxGL._glMap.queryRenderedFeatures([[e.latlng.lng - 1, e.latlng.lat - 1], [e.latlng.lng + 1, e.latlng.lat + 1]]);
  
  // C: example of not passing any clicked location which returns ALL features in the current map extent
  const features = layer._mapboxGL._glMap.queryRenderedFeatures();
  console.log(features);
});

@jwasilgeo jwasilgeo changed the title Add vectorTileLayer API to access underlying data Add vectorTileLayer events API to access underlying data Mar 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant