Closed marcusdiy closed 4 years ago
I talk similar topics at here. https://github.com/mapsplugin/cordova-plugin-googlemaps/issues/2804
First of all, you need to understand how this plugin is implemented. This plugin generates a native Google Maps view in Android/iOS, then put it under browser view.
Why map view is under browser view? Because many people wants to display a dialog over map, and put a button on map, and so on.
Browser draws HTML elements like a paint on a canvas.
So, there is no way to insert a map view between <button>
and <body>
.
That's why this plugin put a map view under under browser view.
Then change the background color of all parents of the map div.
I hope you catch up at this point.
Then why does this plugin needs to check all positions and sizes of all elements. Let's explain with this image.
A map is displayed like this.
Then if I open a side bar menu like below, you expect you can touch the side bar menus.
However, if this plugin does not watch all positions and sizes of all elements, you can not touch the side menus. Because the maps plugin does not know there is something over the map. In order to understand this, you need to know how this plugin handles touch events.
This plugin insert a transparent native touch layer onto top of the application at first. This means this plugin catches all of touches at once.
Then the maps plugin needs to detect you touch for either map or browser. In order to decide the touch is for map or browser, this plugin needs to know all positions, sizes and hierarchy of all elements in native side.
If all developers want to display map in full screen, nothing to do that. However, not all of them. Some developers want to display in list, small rectangle, or part of page.
So, if you rotate your phone, window
resizes all of elements, then changes of all of elements, such as position, size.
Also, if you display a HTML dialog suddenly, the HTML hierarchy is changed.
If this plugin does not know there is a modal dialog box over the map, you can not click on the dialog box.
If you catch up at here, please move on the next.
Then what is the __plugindomid? As I explain above, this plugin needs to know the status of all of elements.
This plugin create a virtual DOM tree inside this plugin. In order to manages the HTML elements, this plugin uses __plugindomid.
This ID will be hidden in the next version. If you want to use it soon, you can install the next version of this plugin code from the multiple_maps branch code.
$> cordova plugin install https://github.com/mapsplugin/cordova-plugin-googlemaps#multiple_maps
How to improve the performance?
As I explain repeatedly, this plugin needs to know all positions, sizes and hierarchy of all elements.
If 100000 elements are existed in <body>
, this plugin checks 100000 elements.
However, if you certainly know child elements do not go outside from parent node (such as list), there is a way to reduce the check numbers.
The trick is shadowDom
.
For example, there is a list like this.
<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>
If you use shadowDom
, this plugin does not inspect inside the element.
<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>
In this case, this plugin can reduce the number of checking elements significantly.
At the end, I hope you understand correctly.
However, even if you use shadowDom
technique, this plugin still needs to monitor all elements. If you does not prefer that, please use different plugin.
I agree this plugin does not cover all usage cases. Some people prefer performance instead of benefits of this plugin. I don't push this plugin to you mandatory. Please test this plugin deeply, and decide to use or not carefully.
We will put a $150 bounty on anyone willing to dig into the source files and modify this so the plugin on Android, iOS and browser to take the native touch layer, and put it behind webview and can be active state only when a user is on map page. Or some other such modification so that this plugin doesn't need to listen to every DOM node style change/touch and can be used with performance as a primary. If we get no bites, we will try to dig in too but it might take over a month with out back log and we'd prefer not to wait.
Please fork this plugin repository, and you can ask the job to someone else, but not here please.
Ok, i misunderstood. I tough that by "touch layer(native)" you were referring to and document level event listener. So this plugin places one layer under the webview for the map + another layer over the webview to handle all events... I tough that all the events were handled first by JS and then passed to the map plugin. So it is required to check if the element clicked is the map or not. In this case I think it would be possibile to use: document.elementFromPoint(x, y) wich will tell you exactly which element was clicked... this way it's even simplier! And it has great browser support... https://caniuse.com/#feat=element-from-point
I tough that all the events were handled first by JS and then passed to the map plugin.
Technically impossible. If you doubt, please try that by yourself. Android allows to fire virtual touch event, but iOS does not allow. That's why.
This plugin has long years history. I tested many ways as much as possible, then the current style is the best.
If you don't satisfy, I recommend you use different plugin or try to implement by yourself
Please tell us your new feature idea Hi, I would like to use your plugin but currently it has performance issues...which make it unusable. Each time the plugin is installed the dom is immediatelly polluted with __plugindomid, even if not used.
I get that is used to monitor and reference the position of the maps... but this way it slows down the entire app. I look for an explanation about that part, and found an description here.
I would suggest an function which updates the map position manually without polluting dom and data. In a lot of use cases(at least for me) the map wont even be moving a lot and even if it would be the case, adding an single passive scroll + resize eventListener will pretty much solve all the problems related to positioning.
The purpose of the plugindomid is to catch the hierarchy of HTML elements. Why do you need the hierarchy? You can get the exact position via getBoundingClientRect, if that is the problem...
This plugin inserts a transparent layer over the webview, then detect which is clicked, map or HTML element. Over or under? Dont you just need to listen to the events on the assigned #map element? The map will never be clicked if I'm right... that is because it is under the web-view. Right?
In order to detect, the plugin must know the hierarchy of all HTML elements. In order to detect, what? The position? The events?
If a HTML element change, but it might be a parent element of something. If an element is removed from the dom it would trigger a resize event or even scroll event... call .updateMapPosition() How do you check currently if an element was removed?
Without the plugindomid, the plugin needs to trace all HTML elements when any elements are changed. I think that using the mentioned methods there no need to track every dom element...
Why do you need it? How helps other people? Cleaner code and maybe better performance and easier memory management
Please, help me understand that parts so I can try to implement it in this way or leave it as it is, if the current implementation cant be changed or if my proposed approach is slower.