-
Notifications
You must be signed in to change notification settings - Fork 78
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
Interleaved support with DeckGL #8
Comments
Just to add some implementation thoughts to this: In order for the interleaving to work, the React wrapper would need to implement the This is how it works in the GoogleMapsOverlay in deck.gl, the https://github.com/visgl/deck.gl/blob/master/modules/google-maps/src/google-maps-overlay.ts#L246-248 The React wrapper is already special-casing deck.gl in some places, for example here to update the view state, so it doesn't seem unreasonable to support the render callback |
I'm not sure how that would work, and I certainly have to look into how that is done for maplibre and mapbox. My current understanding is that we need to use the |
@felixpalmer can you maybe provide some hints how you achieved that in react-map-gl? I can't seem to find any mention of that in the docs, so have to dive into the implementation.. |
Just curious, is it possible to create a working example right now that supports all basemap variants (maplibre/maplibre interleaved/google maps/google maps interleaved)? Even if it requires lots of ugly conditional cases, it could be instructive to help us see where simplification/API unification opportunities are. I am not really up to date on how all the different variants look, hard to weigh in without seeing where we are at today. |
The Here is an example of how react-map-gl does it: https://github.com/visgl/react-map-gl/blob/master/examples/deckgl-overlay/src/app.tsx |
@Pessimistress I'm aware it isn't currently supported in the |
I've been thinking about this for a bit, and I think there's a viable solution. This is just a rough sketch, so everything is subject to change and there might be a lot of details I glossed over or don't yet know about. Still, maybe worth putting this here for discussion anyway: In case of For interleaved rendering the control of rendering is the other way around: the To get this to work in the The DeckGL component could create the overlay classes needed ( A schematic implementation for this would roughly look like this: // a class implementing this interface is returned via ref from all
// map-renderers
interface MapRendererInterface<T = any> {
rendererType: string;
mapReadyPromise: Promise<T>;
map?: T; // google.maps.Map | mapbox.Map | maplibre.Map | ...
}
const DeckGL = props => {
const mapRenderer = findMapRendererComponent(props.children);
const [rendererApi, setRendererApi] = useState(null);
const rendererRef = useCallback(api => {
setRendererApi(ref);
});
useEffect(() => {
if (!rendererApi) return;
rendererApi.mapReadyPromise.then((map) => {
createOverlay(rendererApi.rendererType, map);
});
}, [rendererApi]);
// omitted: handling of all other children
return <>{React.cloneElement(mapRenderer, {ref: rendererRef})}</>;
}; So what would happen here?
A couple of things to note:
What do you think of this approach? I could go ahead and write a very minimalistic implementation of such a DeckGL component to see how those parts would work together. |
I like the big ideas here. Can we make it so that deck.gl core doesn't need to know about the different renderer overlays (its just the applications that needs to know them, import them from their modules etc)? Maybe adding any required As a total nit, I prefer shorter names: interface MapRenderer<T = any> {
type: string;
mapLoaded: Promise<T>;
map?: T; // google.maps.Map | mapbox.Map | maplibre.Map | ...
} |
I was thinking about having some sort of global registry (effectively a // in @deck.gl/mapbox
import {registerOverlayType} from '@deck.gl/core';
registerOverlayType('mapbox', MapboxOverlay); // in @deck.gl/googlemaps
import {registerOverlayType} from '@deck.gl/core';
registerOverlayType('google-maps', GoogleMapsOverlay); This is assuming a common interface for all overlays, but since they are very close already this shouldn't be a huge problem (it looks like The Bonus benefit: If at some point someone wants to write react components for e.g. openlayers they could implement all the deck.gl integration without needing any changes to deck.gl itself. |
We have had a few examples of global registries in the vis.gl frameworks (for instance loaders.gl allows for global loader registration), but usually (like all things global) these end up eventually being more pain than they are worth, and kind of promote debatable coding practices. The above is not a veto but rather just a soft vote against it. Would asking the application to pass in an |
Sure, that would work as well. |
With this approach, Deck would be responsible for creating the Overly (MapboxOverlay or GoogleMapOverlay) which is a great abstraction but the camera control would be still in the
It could be a bit confusing for the user why sometimes you send the
I'm asking this to make sure I understand the approach correctly. |
@padawannn I'll keep that in mind, thanks! Which component is actually controlling the rendering should just be an implementation detail, and isn't relevant to the outside. When rendering via Overlay, it can still be the DeckGL component that receives the view-props. In that case the values would only be forwarded to the map-renderer since the Deck instance will receive the values to use via the overlay. |
Thanks for taking the time to think about this @usefulthink and the detailed writeup!
I would be very interested in seeing such an implementation 👍 |
I just want to point out that:
Having the parent component render after the child is an anti-pattern in React and will lead to all sorts of unexpected problems. What if there are multiple map components in the children? What if the child map is later removed, shouldn't it behave like using DeckGL standalone? The component is already complicated as is, do you really want to sacrifice stability to save a few lines of client code? |
Not to downplay the issues you mentioned @Pessimistress but there is value beyond saving lines of code. By having deck control the camera and user input we make it possible to have a consistent experience across the basemaps and enable other libraries that work with deck, like nebula.gl integrating with the interleaved basemaps. Ideally we would support adding/removing the child map and transitioning to DeckGL standalone, in effect this permits swapping between basemaps. We could use types to limit the number of children to one, and at runtime simply ignore additional children. |
Are we still talking about the same problem? Non of the existing interleaved options use Deck's camera control. This is not really up to us. |
I think a consistent experience is a great goal to work towards, however I don't think it's currently possible to have total consistency (but we can get close!). In my experience interleave implementations are only as good as the least-featured hook for any given integration. Deck tends to have the more feature-ful hook compared to basemap libraries (historically this included webgl 2, many view types, multi-view, devicePixelRatio override, to name a few) for reasons ranging from performance to preference. We could encourage basemaps to make public apis and support more features, and until then Deck needs to be conform a bit to interleave properly. Deck v8 straightened out an ownership model with maplibre/mapbox so that they always control deck through the I would love to see a similar pattern in place for google maps too, and like a lot of the ideas in here. My main piece of feedback would be to use a basemap -> deck control flow, make consistency a non-goal in the initial implementation, and encourage the basemaps to prioritize a consistent and featureful api for deck to integrate with in the long term. Publishing a deck interface/spec for integration, something like As a sidenote, hubble.gl and nebula.gl have the same challenge in wanting to configure both the deck and basemap integration. I don't think |
Lots of deep thoughts here. Just wanted to mention that in the last open governance meeting we floated the idea of setting up an Open Visualization "basemaps working group" - the idea would be similar to the binary data, 3D and widgets working groups - to create more focused collaboration here, perhaps with some meetings where we could discuss in detail, hash out a common roadmap etc. |
I would be very interested in joining that working-group once it is formed. |
The key enabler is to have someone step up and take the WG lead role, at least temporarily. Currently we have
If you are interested I could spend some time to help you set up the roadmap and the working group slack channel etc. |
I would like to open a discussion about Interleaved support.
Imagine that you have a DeckGL project where you want to change between MapLibre and Google Maps with interleave control. For MapLibre you would have something like this
where the camera control is done by Deck but if you change it to Google Maps with interleave support you would have something like this example where the map camera control is done by the Google Maps component instead DeckGL.
It's difficult to maintain and it can also be difficult to integrate with libraries like NebulaGL that interacts directly with the map events. So my question is if there would be a way to support interleave while keeping Deck as a wrapper of the map, for example:
The text was updated successfully, but these errors were encountered: