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

feat(map): allow map instances to be rendered on top of webview #161

Open
tafelnl opened this issue Apr 6, 2022 · 5 comments
Open

feat(map): allow map instances to be rendered on top of webview #161

tafelnl opened this issue Apr 6, 2022 · 5 comments
Labels
enhancement New feature or request

Comments

@tafelnl
Copy link
Member

tafelnl commented Apr 6, 2022

Right now, the plugin deliberately renders map instances below the webview. This allows for overlaying the map with anything that's in the webview. This way it is possible to customize the map with custom-made HTMLElements like a "to my location"-button for example. Also this allows for use-cases, where you can show full-fledged HTMLElements - like cards - on top of the map, when you click a marker for example.

As can be read in the Should you use this plugin? section of the documentation, the main use-case of this plugin is for apps which main focus is the map:

If your app revolves mainly around a Map, like for example Uber or Lime, this plugin is probably a good fit for your concept.

However, this approach actually makes it more difficult for developers with "simple" use-cases to implement this plugin. For example in issue #154, a developer mentioned he'd like to use this plugin in a modal. As said before, those type of use-cases are not the main focus of this plugin.

Right now a developer would need to make every element (including the modal) transparent to make the map visible. This can be sub-optimal in certain scenarios. Especially when utilizing a modal.

We'd like to add a feature that makes it easier to utilize this plugin in similar scenarios. We will be doing that by adding a renderOnTopOfWebView (or something similarly named) parameter to the createMap method. When this parameter is set to true, the map instance will (as its named suggests) on top of the webview, instead of behind it. That way it is not needed anymore to make all kinds of HTMLElement transparent.

Of course this has the drawback that all advantages that come with rendering behind the webview, are not applicable for that specific map instance. So we will need to document this option clearly, so that a developer can make a rational decision between the two types of rendering.

@va2ron1
Copy link
Contributor

va2ron1 commented Apr 11, 2022

Again, he says is using Ionic. This framework use shadow dom for almost everything and makes pretty difficult to determine every use case like modals. I'm still use this approach just for the modals, but I think a custom event for every load/unload map can work for the developer to do the necessary work.

For Ionic framework:

// Load
self.bridge?.webView?.evaluateJavaScript("document.head.insertAdjacentHTML(\"beforeend\", `<style>.cgmn { --background: transparent; } .cgmn_outlet { display: none; }</style>`)", completionHandler: nil)
self.bridge?.webView?.evaluateJavaScript("document.querySelectorAll(\"ion-content, ion-modal\").forEach(x=>x.classList.add('cgmn'));", completionHandler: nil)
self.bridge?.webView?.evaluateJavaScript("document.querySelectorAll(\"ion-router-outlet + ion-modal\").forEach(x=>x.previousElementSibling.classList.add('cgmn_outlet'));", completionHandler: nil)

// Unload
self.bridge?.webView?.evaluateJavaScript("Array.from(document.querySelectorAll('.cgmn')).forEach((el) => el.classList.remove('cgmn'));", completionHandler: nil)
self.bridge?.webView?.evaluateJavaScript("Array.from(document.querySelectorAll('.cgmn_outlet')).forEach((el) => el.classList.remove('cgmn_outlet'));", completionHandler: nil)

Note: The Javascript can be improve.
Note 2: The close/unload part from v1.x doesn't exist in v2.x

@tafelnl
Copy link
Member Author

tafelnl commented Apr 12, 2022

Could you elaborate on what you mean with close and load?

@va2ron1
Copy link
Contributor

va2ron1 commented Apr 12, 2022

For this plugin, load means the map creation (createMap) and the unload/close is suppose to be the destruction of the map but doesn't exists.

This could be useful events:

  • before the map is created
  • after the map is created
  • before the map is destroyed
  • after the map is destroyed

Other useful events:

  • before and after adding or removing a marker

@tafelnl
Copy link
Member Author

tafelnl commented Apr 14, 2022

Events

Regarding the events, I am not sure if sending events for those events you mentioned would be useful, since the events are being triggered directly by the code of the developer itself. So for example, take the following pseudo-code:

onMapCreated((event) => {
  const mapId = event.mapId;
});

createMap();

I don't think it offers much added value as compared to just:

const { mapId } = await createMap();

Hiding background of specific elements

I understand that adding code that will handle hiding backgrounds of several Ionic elements would be useful to a developer. But as mentioned in the docs it is a deliberate choice to not implement this in this plugin:

This is a deliberate choice, because this plugin could impossibly take care of all the different project setups and an infinite number of different CSS possibilities.

It would also be a bit misleading, since we cannot prevent all cases where a developer will need to handle hiding backgrounds of other divs anyway. So I think it is better to just state explicitly and clearly that this plugin will not hide any background at all. And that the developer will need to take care of this himself.

However, what I think we can offer instead, is a recipe book that writes out a couple of common uses, like the one you wrote down.

But I think this discussion is not related to this specific issue anyway, so if you disagree with me on something regarding this, please open up another issue/discussion :)

@va2ron1
Copy link
Contributor

va2ron1 commented Apr 14, 2022

I only mention those css lines as an example of what I'm doing inside the plugin, not to add it to the plugin, that part I'm clear from the other topic.

And continuing with the example for better understanding. This could be a use case with some of those events.

// before creating the map
onMapBeingPrepare((event) => {
  const mapId = event.mapId;
  
  // the developer does what he/she has to do like
  // get the modal and hide the background
});
// before destroying the map
onMapBeingDestroy((event) => {
  const mapId = event.mapId;
  
  // the developer does what he has to do as
  // get the modal and show the background
});

Or inject the css as I'm doing in the other example.

The destroy part is only for the developer who is not using any framework, like using pure Capacitor. It's not the same as doing the following example because there are a lot of things happening just by calling that line of code.

// get the modal and hide the background
await createMap();

At least in iOS for the developer to make a smooth transition for the user this has to be done after creating the GMSMapView and before adding it to the view and that's what the custom event is for. This way the plugin can give us the necessary options to work any kind of situation, like displaying the map instance over any HTMLElement.

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

No branches or pull requests

2 participants