mapsplugin / cordova-plugin-googlemaps

Google Maps plugin for Cordova
Apache License 2.0
1.66k stars 918 forks source link

Listing for domNode position and pointer/touch events on webview above #2804

Closed Mapiac closed 4 years ago

Mapiac commented 4 years ago

Quick question that might be helpful for some, I see the 2.7.1 is removing the pluginDOMid, kudos to Masashi! That's awesome.

We persist the map under our webview, (not only the transparent webview) when using the map, but always in an effort to make the transition to map feel native (remove delay and flicker). We use a single map (multimap branch) so somewhat unorthodox use (not primary use case or how it's designed - for new folks reading this). However, we recently started using InteractJS pointer event library, and as you can see pointerDown is ~200ms and dips into the native. Not asking for any tips on that library. I think this is the reason our scroll above the map, has some perf issue do to us persisting it below at all times.

So was wondering if you can point me to the code in the plugin that;

a) listens to DOM node position b) listens to the touch events

We want to try and enable only via JS once the user is on map. We will make map 100% of screen and then persist (lock it) under the feed webview, until user gets back to the map at which point we will resume it. Thanks! Long time user of the plugin.

https://github.com/taye/interact.js/issues/840 image

Mapiac commented 4 years ago

I might add this one too. The node I am selected on is for maps, coming from transitionEnd way before

image image

wf9a5m75 commented 4 years ago

I can't understand what you want to know, and I've never used Interact.js (I checked the interact.js, and that's interesting library)

I guess you might feel a little time lag for dragging something because of this plugin. Yes, that could be happened. Because this plugin monitors all DOM elements.


In that case, please use shadowDom. This plugin does not monitor inside shadowDom elements.

For example, there is a list, and the list has tons of items inside it, like below. In this case, the maps plugin needs to check all elements of list items, that takes a little time.

<style>
  .list {
    width:300px;
   height:300px;
    overflow-y:scroll
  }
  .list-item {
     width: 100%;
     height: 50px;
  }
</style>
<div class="list">
  <div class="list-item">item</div>
  <div class="list-item">item</div>
  <div class="list-item">item</div>
  ..... (repeat 100000 items)
  <div class="list-item">item</div>
</div>

But you certainly know the <div class="list-item"> items do not appear outside of <div class="list">. In that case, you can create a shadow dom, so the maps plugin checks only the <div class="list">.

<div class="list" id="list"></div>   <--- Maps plugin checks only this element

<script>
  var list = document.getElementById("list");

  var container = list.attachShadow({mode: 'open'});  // or 'close'
  for (var i = 0; i < 100000; i++) {
    var item = document.createElement("div");
    item.addClasses("list-item");
    container.appendChild(item);
  }
</script>

I don't know how you use the interact.js in your app, but wrapping with shadowDom (or creating a custom component) reduces the maps JS processes

I hope this works for your app.

Mapiac commented 4 years ago

Thank you Masashi, very thoughtful, considered answer. Using shadowDOM is something we didn't consider. Will explore and consider with the team today and post back findings on that. Yes I recall when you did the 2.0 ^ refactor you at that time changed to listen to ALL DOM nodes (rather than just DOM nodes under) https://github.com/mapsplugin/cordova-plugin-googlemaps/issues/1522 < that was the change.

I am thinking out loud here in case you also have an idea but what would the consequences be to not listen at all (position?), or to modify it a bit so that map only listens to one static DOM node -instead of monitor all of them (we have a wrapper that we hardware accelerate for rendering and we could use that). My prior post I was thinking about why we were monitoring all (this thought), and also how we could prevent the map under, from listening to touchEvents on the feed (UL) above (when map doesn't need to know what's occurring). Will report back on shadowDOM. Thanks!

Mapiac commented 4 years ago

Hmm so our use of map is fullscreen, once clicked to visit map. It has a webview search header, but we could just put that header to have a higher zindex and float it over the map, instead of pushing down map 44 pixels at top when shown. Making map 100% instead of 95% and doing that defines map position when going to map and makes that easier.

We are thinking about what we can modify to make the map only listen to one div that might be our lowest static div and from that it can position. Instead of all divs.

On the listeners, because it's a distinct button click to get to map, having the map listen to all touch gestures and pointer events seems like something we shouldn't be doing, instead enabling on mapShow/reveal.

image image

wf9a5m75 commented 4 years ago

I don't mind if you do that on forked repository. That's open source code.

I believe most people prefer "automatic decision".

For example, let's assume your app displays a modal dialog above a map. It means you want to receives the touch by the modal dialog, but if the maps plugin watches only the map div, the dialog can not receive the touch.

Of course, if you monitor the modal dialog, then the maps plugin can detect correctly. But you have to remove the information when the dialog disappear. Something, something. You need to keep watching all necessary elements by your code.

So, you might get more high performance, but I think your code would be messy. I think shadowDom solves your problem easily, and stay focusing on your main logic of your app is better instead of diddling the plugin code.

If you are interested in, please read https://github.com/mapsplugin/cordova-plugin-googlemaps/blob/master/www/js_CordovaGoogleMaps-for-android_ios.js

And if you could be able to improve the performance, please send a pull request.

Mapiac commented 4 years ago

We might try some Mods. Do you know off-hand all the spots where;

a) the map listens to the DOM node positions b) map listens to touchEvents

Absolutely if we can make progress we will do a pull for your consideration. This would be handy if you know ^. We will try a few things but this might make it easier as there are many js files in the map plugin.

Your example of the model, good point. My thinking for a way to go about that has a boolean listener that determines who gets the touch -map vs everything (webview above, map, model etc). Throw the model, set map listener false. If false, the map and webview get the events (how the plugin is now). You would run this on opening the modal from the default of true.

Else, map listener is true and only listens on the map alone. When the webview feed shows above covering the map, we would use this (so the map is not listening to everything going on). Different approaches to the same problem might be use the mutationObserver already being used. The mutation observer normally watches for every change to the DOM to see if the map should check for updates. So deactivating that and set it to only watch for changes to the position of the .custom-scroll (our wrapper that we hardware accelerate...almost at the root), which is always positioned offscreen when the map is shown and vice versa.

What's your thoughts on these strategies (yes we plan to try) but creatively? Limitations you can think of? We are still looking at shadowDOM but there are some issues with that which is that the app's logic and styling currently violate both of those restrictions, so wouldn't be a quick change to edit the feed to use shadow DOM. Also either of the first 2 ideas if we can make work would be easier adoption for others to easily use as an option.

image

wf9a5m75 commented 4 years ago

I don't mind if you charange your ideas on forked repository. But I don't have a plan to change the automatic decision way (I spent tons of time for this problem, and now stable)

Tentatively, please read the code and understanding the logic of the plugin code is the first step.

CodeWithOz commented 4 years ago

@wf9a5m75 thanks for the detailed explanations and suggestions! I'm trying to develop an understanding of how the code translates into the explanation of how the plugin works. Quick question: the plugin inserts a transparent layer that is used to monitor touches, is that layer done in html/javascript (the map div maybe?) or in native java/objective-c?

wf9a5m75 commented 4 years ago

It's in java/objective-c

CodeWithOz commented 4 years ago

@wf9a5m75 thank you. The shadowDOM option isn't viable for us right now, so we're considering making changes in our own fork. Can you please provide some guidance on how/where we can edit the native code to deactivate the layer and the checks for touches when we know for sure that the map isn't being viewed (and reactivate it when we know it's being viewed)? We don't have anyone on our team who is familiar with java/objective-c so we're a bit limited and it would be amazing if you could provide just some direction on which files and/or lines of code that we likely need to change. I know that we can add methods to the cordova plugin, so my current idea is to create a plugin method that we call when we know the map should be shown/hidden. I can do the javascript part but need a little guidance on how/where to edit the native code. We would greatly appreciate any help you can offer, thank you!

wf9a5m75 commented 4 years ago

I prefer the person who do best efforts of the person as much as possible.

It's easy to give the solution for your purpose, but in that case, I have to take care of your case until the end and you don't improve your self.

Please just read this file, and try to understand. Most main control logics are written in JavaScript side. Native side executes the command only.

Even the touch logic, detection logic is implement in native side, but switch is implement in JavaScript side.

You only need to understand this file. No other files are necessary for your purpose. All code in the file is written by JavaScript. So you can read all code. If you understand correctly, you can find the answer easily.

Please do your best. Only necessary action is to read this file.

https://github.com/mapsplugin/cordova-plugin-googlemaps/blob/master/www/js_CordovaGoogleMaps-for-android_ios.js

wf9a5m75 commented 4 years ago

Since there is no plan to provide switching the option (turning off/on), but the PR for improving the process performance is welcome.