mapsplugin / cordova-plugin-googlemaps

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

Performance problems when adding many markers. #835

Closed atannus closed 8 years ago

atannus commented 8 years ago

I'm proposing a patch to the PluginMarker.java file that will greatly improve the performance when adding hundreds of markers to the map.

I propose the creation of a createMarkers method (note the plural), which will take the same marker definition as does the currently available createMarker, except for the fact they'll be in an array, therefore allowing the creation of multiple markers with a single over-the-bridge request. Naturally, the callback has to return an array of markers, instead of a single marker.

A private createMarker_ method is to be called by createMarkers. This does not break the current API, and the current createMarker method can be refactored to simply call the private version with its argument in an array.

I have already implemented marker caching and marker pre-loading which on top of that will drastically reduce memory consumption and prevent leaks.

This is where my understanding of this project ends. I don't know what my constraints as a developer are:

I'm seeing fantastic performance with these improvements, I'd really like to contribute them.

Thanks a lot for the help.

hirbod commented 8 years ago

IMHO it should be a plugin feature

atannus commented 8 years ago

It's not a matter of opinion, it's an application of the principle of separation of responsibilities.

On Thu, Aug 25, 2016 at 9:30 AM, Hirbod notifications@github.com wrote:

IMHO it should be a plugin feature

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/mapsplugin/cordova-plugin-googlemaps/issues/835#issuecomment-242368921, or mute the thread https://github.com/notifications/unsubscribe-auth/AAo2mxnFCbFWsY-PzCt3KfM0_ehtEGZlks5qjYrwgaJpZM4HQ9q5 .

André Tannús | Epungo | +55 11 2389-4360 We are a layer

hirbod commented 8 years ago

Well, this is your opinion. Google and other map frameworks provide SDKs for creating clustering on client side. It's there for reason. Server-Side Clustering can be a heavy database and CPU consuming process and there is need for beeing able to do this clientside. Not always, but for enough people.

atannus commented 8 years ago

Exactly.

Google and other map frameworks provide facilities for clustering, they don't handle it internally, which is precisely what I am proposing. Again, see Feb 3.

I never said server side was better, I said it was in line with not being handled by the Maps Plugin. What I did say is that clustering should done by the user, not by the plugin. Whether it bill be done in the device or server-side is up to the user.

If clustering is too intensive you have yet another reason why it should be done server-side, and cached.

Mojo90 commented 8 years ago

@wf9a5m75 so what do you recommend me? (Of course I was aware of this thread but opened a new one because I can't see a solution out of this one)

wf9a5m75 commented 8 years ago

This is the demo that current status.

APK https://drive.google.com/open?id=0B1ECfqTCcLE8QVBWNl9pd2lyX00

Video https://www.youtube.com/watch?v=sUJDKbFf_Jo

Mojo90 commented 8 years ago

So pls let me make a conclusion:

is that right?

--> If yes: pls understand as mentioned before by lots of other people that time is a limiting factor for most of us. Thus I would prefer if you can make a statement if it would take 3 months, 6 months, 1 year, 2 years or 5 years for you. It is not important if this is exactly right but than everyone can decide how to proceed with his/her project and this maps plugin.

--> If no: Maybe the other people here should decide to make a fork to get some more features in it and than it would be okay as well because from my point of view the only thing I currently missing is marker clustering, with this feature it would resolve all my open problems with the map I think.

P.S.: I really can not understand why everyone else has stopped working and lots of people (myself as well) have offered their support without feedback, which is killing the open source mind in my opinion. If sb. can link me to a previous discussion about the future of this plugin that I can comprehend this would be great, thx.

wf9a5m75 commented 8 years ago

@Mojo90

In current stable version (1.3.9) it is not possible to get satisfying results with a bunch of markers (maybe 500 or 1000+)

Yes.

marker clustering is needed to get a great result and UX (no lagging anymore, no overlaying markers etc.)

Yes, but I haven't develop it now (I developed this at once, but not ready yet).

you (@wf9a5m75) are currently developing version 1.4 of this plugin which will resolve all this issues

Yes, except the marker cluster. And adding the feature of multiple maps, and etc.

Even though you saystime is a limiting factor for most of us, my private time is also very limited. This is NOT company's product, this is just hobby code.

I applicate for offering to help, but during the developing, the code (and internal mechanism) will change severely. That's why I don't accept any help right now.

I can not promise the ETA, since even for me, the unknown new issues are happen in order to implement the safe feature for Android and iOS.

I don't mind that you folk and create your original version, if you don't satisfy the current status.

Mojo90 commented 8 years ago

@wf9a5m75 thx for your answer. I assumed that this is your hobby code as it would be for others contributors. But I think you must understand that some people rely on plugins for commercial products and so its better to share the load of developing new features and optimize old code with others. but imho what you are doing right now since beginning of this year kills all the good reputation this plugin earned in the past. But its your decision, you are the initial author so let me say "its your baby".

As this thread has Milestone of 1.4.0 I assume marker clustering will be included in the next release you will publish (whenever it will be).

wf9a5m75 commented 8 years ago

@Mojo90 I don't mind if you or other people use this plugin for commercial app, but it's not related to me. If you force me hurry up, it's easy. You just pay $1,500,000 for the company I belong to. It makes me a time to focus on to this plugin during the work time for a few weeks. But you probably don't want pay it, there is no time to improve my time. Otherwise, you should create your version. I'm really stressful for pushing your schedule, that's why I open this plugin as open soirce and loose license.

I won't include marker cluster for next version at least.

Mojo90 commented 8 years ago

I see, no problem. I think its best way to do my own version even if you will not include clustering in the next version, because this is the feature I am waiting for almost a year now. I already thought about this a year ago because it needs ~100 LoC per platform from SDK point of view, isn't it? But than @Hirbod implemented it with other developers and it was never released - also another strange story. But nevertheless @wf9a5m75 a great plugin, thx!

But than please remove Milestone 1.4.0 from this thread that this will not mislead other people, because this issue won't be fixed with next version.

cvaliere commented 8 years ago

this plugin is not "a great plugin", it's a shitty plugin with shitty performance, tons of bugs and a ridiculous limitation to a single map, and that's exactly why @wf9a5m75 is rebuilding it entirely; for the joke, branch "multiple_maps" is 179 commits ahead of master, and if you make the diff, you'll see that not a single file has been spared from this total rewrite

@wf9a5m75, would $1000 encourage you to hurry up?

wf9a5m75 commented 8 years ago

@cvaliere Thank you for your patient. I'm working on everyday recently. I can not promise you but it's not so long far to finish up. Temporally ETA is end of this month (PDT).

Thank you for offering the amount, but I can not receive it since even receive it, my free time is not increased. I only receive your kindness.

Mojo90 commented 8 years ago

@cvaliere I already thought of use cases for multiple maps, can you please tell me some? nothing very important came in my mind...

adrinavarro commented 8 years ago

@Mojo90: What do you mean? Multiple maps simply means that you can initialize multiple maps. In our case, this means we can have a tab with a map ("always on") then initialize and destroy maps as needed for detail cards, settings, etc.

cvaliere commented 8 years ago

same here: we have a permanent tab with a map, and we also want to have occasional maps for detail cards

hirbod commented 8 years ago

@cvaliere you should really leave this forum. I'm sick of your attitude. When this is a shitty plugin and has ton of problems for you (because it just don't fit your needs), go ahead and develop your very own version. I don't know who you think you are. When you want to build something commercial then go ahead, hire an iOS and Android developer, pay like 5000-8000 € per month and create your own, perfect, non-shitty plugin and be disrespectful with them. After that, create a Git, and share your perfect solution with everybody.

If not, shut the hell up. I really don't know how you even dare making demands on an open source project.

Mojo90 commented 8 years ago

but you can remove markers and readd with new and restyle map if needed. or what is the problem here? From performance point of view isn't it better to just add one and fit that map according to your needs?

hirbod commented 8 years ago

@Mojo90 while your solution is legit, it's not so snappy. You will always have a little small delay and flickering. Multiple map instances will give you the ability to keep your "main" map, and create another one. (maybe a smaller version, which has focus on a special location or something)

cvaliere commented 8 years ago

@Hirbod I was expecting someone to react like you :)

Let me just remember that I offered my own help as a developer 6 times in this thread, always refused; I spent dozens of hours to test this multiple_maps, never worked; and I even made my own fork to try to make it work, but it was so buggy that it was pointless

What makes me sick is that this "open source" project is not open source anymore, since @wf9a5m75 decided, 7 months ago, to refuse any contribution, saying that he would handle everything by himself; and since then, we're all desperately waiting for something to happen

Sorry if "shitty" offends you, but when you see that master branch is 40 times (!) slower than optimization branch, the only conclusion you can make as a developer is that it's really bad; and apparently, @wf9a5m75 came to the same conclusion, as he is rewriting everything

If you disliked my "attitude", at least admit that I do what I can to make this "open source" project evolve; I don't "make demands", I'm offering my contribution, which is refused; and now I'm offering money

hirbod commented 8 years ago

@cvaliere Just let him finish the multiple map branch, and after that, we all will appreciate any help we can get.

The current problem is (maybe due to @wf9a5m75 workflow), he works on multiple branches, locally + remotely (and also changing codebase quickly) etc, and any help would make him lose his track as he has to cross-merge etc. (at least I am thinking it is like that).

After multiple maps is finished (which hopefully has the optimization incorporated), we have a "new master" which we can work on together - and a better organized github structure.

cvaliere commented 8 years ago

and I will be happy to contribute to this new master happy to know it could happen by the end of the month

wf9a5m75 commented 8 years ago

@Hirbod Thank you for helping me.

he works on multiple branches, locally + remotely (and also changing codebase quickly) etc, and any help would make him lose his track as he has to cross-merge etc. (at least I am thinking it is like that).

Exactly. The code changes quickly to fix issues (if I do like this with other people, they have so much stress). That's why I can not accept helping offers.


@cvaliere I know you have so much stress the current status. If I were you (like use this plugin in commercial), I probably have much stress, or start to develop own version.

I will finish the multiple_maps branch working by the end of this month. At least like beta. (Beta means that the no code changes dramatically.)

Merge to the master, or not, I will discuss with @Hirbod at the time.

samazary commented 8 years ago

@cvaliere @Mojo90 +1 for clustering, that is a much awaited feature of this plugin!

AbuHani commented 8 years ago

Hi, +1 for clustering any updates ??

wf9a5m75 commented 8 years ago

Hi everyone. As I said before, today is the day. The next version (2.0-beta) is ready to go (however beta).

First of all, try the demo app. You can download from my dropbox. cordova-googlemaps-v2-demo_01.apk

Demo video of the above apk

https://www.youtube.com/watch?v=oZBkTIpjTqg

screen shot 2016-09-30 at 7 29 16 pm


There are several changes.

change 1 . multiple maps

As you may know, the next version supports multiple map in the same html. However one map takes large memory, so I recommend 2,3 maps at the one page. If you don't use a map, remove it. That's save the memory.

change 2. multiple pages

Version 1.x supports only single html file (typically index.html) The next version supports multiple HTML file (such as index.html, page1.html, page2.html ...etc) You don't need to cleanup the maps if you change html files. The plugin will do automatically.

However, changing tab page in the same html is a different. You need to still do map.setVisible(true/false) by yourself.

change 3. Recognize all html element

Version 1.x supports only under the map div. The next version recognize all HTML element of the page. It means you don't need to execute map.setClickable(true/false) when HTML dialog is popped up on the map div.

Here is the tips If the plugin does not recognize your HTML elements on the map div, specify css

.dialog {
    position: fixed;
    z-index: 1000; //any value is fine
}

Since the html elements that have position:fixed takes a priority always in the maps plugin. (You don't need to do this usually (I believe so))

change 4. save battery life

The problem of the version 1.x is the KeepWatching Timer. This timer watches HTML element positions under the map div periodically. However, if you don't do anything on your app, still the timer is running. This is affect for battery life.

In the next version, the timer stops automatically if the user does not touch on the map anything for a while. If the user touch on the app again, the timer also starts. If no changes for a while, stop the timer again.

If you need to start the timer programmatically, you can do like this:

cordova.fireDocumentEvent('touch_start', {});

or

var event = document.createEvent('touch_start');
event.initEvent(eventName, false, false);
document.dispatchEvent(event);

change 5. performance improved

Another big problem of the version 1.x is that all (most) native code run on the UI thread (or run on the WebCore thread. The reason of this is the Google Maps native APIs require do it. However I tested so much time and rewrite all most whole code in both native and javascript, the most code run on the background thread.

And you are lucky. I work as Android developer usually. I work for one

If you don't understand this talk , you can skip this. Just remember the performance is improved.

change 6. split the JS file

The version 1.x code of the Javascript is googlemaps-cdv-plugin.js The file includes 2873 lines. Wow, it's too large. Not suite for maintenance...even for me.

I split the JS files for each classes (such as Marker.js, Circle.js, etc) https://github.com/mapsplugin/cordova-plugin-googlemaps/tree/multiple_maps/www

You can debug easily :)

change 7. introduce BaseArrayClass

If you are familiar with the Google Maps Javascritp API v3, you probably know the MVCArray class The benefit of this class is you can monitor the events: insert_at, set_at, and remove_at. Using this class, your code would be simple.

change 8. property synchronizing

This is really useful. Most of getXXXX() methods return the values as normal javascript object.

For example, in version 1.x,

marker.getPosition(function(position) {
   // you have to wait the callback
});

in version 2.0-beta

var position = marker.getPosition();

You know what? Since the marker (and polyline,polygon...etc) extends the BaseClass (which is MVC class), you can monitor like this.

markers[0].on("position_changed", onPositionChanged);
markers[1].on("position_changed", onPositionChanged);
markers[2].on("position_changed", onPositionChanged);

function onPositionChanged() {
  var marker = this;
  var position = marker.getPosition();
}

However, map.getVisibleRegion() does not support this way. you still have to use callbak.

change 9. chain programming

In version 2.0, most of all setXXX() methods are able to chain.

marker.setPosition({"lat": ...., "lng": ....}).setTitle("Hello");

change 10. add more events, and renamed

Version 1.x events

event name Androide iOS
event name Android iOS
---|-
MAP_CLICK YES YES
MAP_LONG_CLICK YES YES
MY_LOCATION_CHANGE YES NO
MY_LOCATION_BUTTON_CLICK YES YES
INDOOR_BUILDING_FOCUSED YES YES
INDOOR_LEVEL_ACTIVATED YES YES
CAMERA_CHANGE YES YES
CAMERA_IDLE NO YES
MAP_READY YES YES
MAP_LOADED YES NO
MAP_WILL_MOVE NO YES
MAP_CLOSE YES YES
OVERLAY_CLICK YES YES
INFO_CLICK YES YES
MARKER_DRAG YES YES
MARKER_DRAG_START YES YES
MARKER_DRAG_END YES YES

Version 2.x events

event name Androide iOS arguments[0]
MAP_READY YES YES none
MAP_CLICK YES YES LatLng
MAP_LONG_CLICK YES YES LatLng
MY_LOCATION_BUTTON_CLICK YES YES none
INDOOR_BUILDING_FOCUSED YES YES none
INDOOR_LEVEL_ACTIVATED YES YES building information
CAMERA_MOVE_START YES YES true if the camera move start by gesture
CAMERA_MOVE YES YES CameraPosition
CAMERA_MOVE_END YES YES CameraPosition
POLYGON_CLICK YES YES LatLng(clicked position)
POLYLINE_CLICK YES YES LatLng(clicked position)
CIRCLE_CLICK YES YES LatLng(clicked position)
GROUND_OVERLAY_CLICK YES YES LatLng(clicked position)
INFO_CLICK YES YES LatLng(marker position)
INFO_LONG_CLICK YES YES LatLng(marker position)
INFO_CLOSE YES YES LatLng(marker position)
INFO_OPEN YES YES LatLng(marker position)
MARKER_CLICK YES YES LatLng(marker position)
MARKER_DRAG YES YES LatLng(marker position)
MARKER_DRAG_START YES YES LatLng(marker position)
MARKER_DRAG_END YES YES LatLng(marker position)

change 11. set background color

use plugin.google.maps.environment.setBackgroundColor()

change 12. geocoding/reverse geocoding

You can do like this

plugin.google.maps.Geocoder.geocode({
  "address" : [
     "address1", "address2" ... "addressN"
  ]
}, function( mvcArray ) {

  mvcArray.on('insert_at', function(index) {
     console.log( mvcArray.getAt(index) );
  });

});

change 13. add some features

I forgot to much. See the demo apk.

change 14. Not yet

map.showDialog(), map.closeDialog(), and map.addKmlOverlay() are not ready yet.

change 15. UIWebView & WKWebView

Both are Supported.

Crosswalk is not confirmed yet.

I think I miss something. I will post them if I remember.

wf9a5m75 commented 8 years ago

Oh, I just remember, the tileoverlay, ground overlay support the local image files.

And no longer to start with www/ You can use the relative path for path specify (marker, tile overlay, and ground overlay)

wf9a5m75 commented 8 years ago

Hi everyone,

I prepared the demo apk repository: https://github.com/mapsplugin/v2.0-demo/

If you face any issues about v2.0-beta, please post to the issue tracker of the demo app, instead of this repository. I would like to separate the issues.

wf9a5m75 commented 8 years ago

Okay. Probably you guys are interested in the final result, the v2 is faster than v1?

The test code is here.

var map;
var mockData = [
  {
      lat: "-23.548922600000000",
      lng: "-46.574610800000000",
  },
  {
      lat: "-23.549337900000000",
      lng: "-46.574795600000000",
  },
  {
      lat: "-23.550828933700000",
      lng: "-46.576023101800000",
  },
  {
      lat: "-23.550889500000000",
      lng: "-46.576046300000000",
  },
  {
      lat: "-23.551199100000000",
      lng: "-46.575804400000000",
  },
  {
      lat: "-23.550761500000000",
      lng: "-46.575932700000000",
  },
  {
      lat: "-23.550820100000000",
      lng: "-46.575986100000000",
  },
  {
      lat: "-23.550958200000000",
      lng: "-46.576498800000000",
  },
  {
      lat: "-23.550552368200000",
      lng: "-46.574832916300000",
  },
  {
      lat: "-23.550529480000000",
      lng: "-46.575012207000000",
  },
  {
      lat: "-23.549200058000000",
      lng: "-46.573200225800000",
  },
  {
      lat: "-23.549949646000000",
      lng: "-46.572673797600000",
  },
  {
      lat: "-23.550093900000000",
      lng: "-46.572460600000000",
  },
  {
      lat: "-23.550067000000000",
      lng: "-46.572427400000000",
  },
  {
      lat: "-23.549314300000000",
      lng: "-46.571722400000000",
  },
  {
      lat: "-23.548916800000000",
      lng: "-46.572370800000000",
  },
  {
      lat: "-23.550040200000000",
      lng: "-46.571646100000000",
  },
  {
      lat: "-23.551219500000000",
      lng: "-46.571387300000000",
  },
  {
      lat: "-23.550374984700000",
      lng: "-46.571079254200000",
  },
  {
      lat: "-23.551379900000000",
      lng: "-46.572379600000000",
  },
  {
      lat: "-23.551279068000000",
      lng: "-46.571372985800000",
  },
  {
      lat: "-23.550819700000000",
      lng: "-46.571475300000000",
  },
  {
      lat: "-23.550776800000000",
      lng: "-46.571910200000000",
  },
  {
      lat: "-23.551599502600000",
      lng: "-46.575599670400000",
  },
  {
      lat: "-23.551599502600000",
      lng: "-46.575599670400000",
  },
  {
      lat: "-23.552324295000000",
      lng: "-46.575397491500000",
  },
  {
      lat: "-23.551766600000000",
      lng: "-46.575586100000000",
  },
  {
      lat: "-23.551599502600000",
      lng: "-46.575599670400000",
  },
  {
      lat: "-23.552499771100000",
      lng: "-46.574798584000000",
  },
  {
      lat: "-23.552565800000000",
      lng: "-46.574789700000000",
  },
  {
      lat: "-23.552565800000000",
      lng: "-46.574789700000000",
  },
  {
      lat: "-23.551799774200000",
      lng: "-46.573898315400000",
  },
  {
      lat: "-23.551788330100000",
      lng: "-46.574462890600000",
  },
  {
      lat: "-23.551799774200000",
      lng: "-46.573898315400000",
  },
  {
      lat: "-23.553100585900000",
      lng: "-46.575500488300000",
  },
  {
      lat: "-23.553400039700000",
      lng: "-46.575199127200000",
  },
  {
      lat: "-23.553100500000000",
      lng: "-46.574628900000000",
  },
  {
      lat: "-23.552700042700000",
      lng: "-46.573799133300000",
  },
  {
      lat: "-23.553236007700000",
      lng: "-46.574249267600000",
  },
  {
      lat: "-23.553236007700000",
      lng: "-46.574249267600000",
  },
  {
      lat: "-23.552700042700000",
      lng: "-46.573799133300000",
  },
  {
      lat: "-23.553236007700000",
      lng: "-46.574249267600000",
  },
  {
      lat: "-23.552421900000000",
      lng: "-46.573419800000000",
  },
  {
      lat: "-23.552553176900000",
      lng: "-46.573181152300000",
  },
  {
      lat: "-23.552079300000000",
      lng: "-46.572764700000000",
  },
  {
      lat: "-23.552452087400000",
      lng: "-46.573001861600000",
  },
  {
      lat: "-23.552553176900000",
      lng: "-46.573181152300000",
  },
  {
      lat: "-23.552080154400000",
      lng: "-46.572765350300000",
  },
  {
      lat: "-23.552339553800000",
      lng: "-46.571506500200000",
  },
  {
      lat: "-23.552373800000000",
      lng: "-46.571509900000000",
  },
  {
      lat: "-23.551967620800000",
      lng: "-46.571239471400000",
  },
  {
      lat: "-23.553024292000000",
      lng: "-46.572566986100000",
  },
  {
      lat: "-23.553100585900000",
      lng: "-46.572799682600000",
  },
  {
      lat: "-23.553188324000000",
      lng: "-46.573322296100000",
  },
  {
      lat: "-23.553508758500000",
      lng: "-46.573505401600000",
  },
  {
      lat: "-23.552674900000000",
      lng: "-46.573789000000000",
  },
  {
      lat: "-23.552713600000000",
      lng: "-46.573731100000000",
  },
  {
      lat: "-23.553152200000000",
      lng: "-46.571818300000000",
  },
  {
      lat: "-23.553367614700000",
      lng: "-46.571437835700000",
  },
  {
      lat: "-23.553100585900000",
      lng: "-46.571701049800000",
  },
  {
      lat: "-23.553808212300000",
      lng: "-46.571708679200000",
  },
  {
      lat: "-23.553110600000000",
      lng: "-46.571771400000000",
  },
  {
      lat: "-23.553100585900000",
      lng: "-46.571701049800000",
  }
];
document.addEventListener("deviceready", function() {
  var div = document.getElementById("map_canvas");

  // Initialize the map view
  map = plugin.google.maps.Map.getMap(div);

  // Wait until the map is ready status.
  map.addEventListener(plugin.google.maps.event.MAP_READY, function() {
    map.moveCamera({
      target : mockData
    });

    var start = Date.now();
    addMarkers(map, mockData, function(markers) {
      var end = Date.now();
      alert("duration: " + ((end - start) / 1000).toFixed(1) + " seconds");
    });
  });
  function addMarkers(map, data, callback) {
    var markers = [];
    function onMarkerAdded(marker) {
      markers.push(marker);
      if (markers.length === data.length) {
        callback(markers);
      }
    }
    data.forEach(function(position) {
      map.addMarker({
        position: position,
        icon: {
          url: "http://googlemaps.googlermania.com/img/google-marker-big.png",
          'size': {
            'width': 30,
            'height': 52
          }
        }

      }, onMarkerAdded);
    });
  }
});

Here are results:

npm version1.3.9

47.1 sec
v1.3.9 Master branch / commit caf6ec1099

1.0 sec
v2-beta / commit 906fc04

0.5 sec

Since the v2-beta is too much faster, I will adjust the code. So in the future, may be a little delay.

wf9a5m75 commented 8 years ago

Another test: loading multiple icon from multiple url

Test code:

var map;
var mockData = [
  {
    "lat": -3.818353,
    "lng": -36.046829,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/775893.jpg"
  },
  {
    "lat": -4.337121,
    "lng": -55.832172,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/82426049.jpg"
  },
  {
    "lat": -3.720867,
    "lng": -38.504189,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/40139960.jpg"
  },
  {
    "lat": 5.48118,
    "lng": -61.89723000000001,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/56409210.jpg"
  },
  {
    "lat": -2.397067,
    "lng": -55.18381099999999,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/39748728.jpg"
  },
  {
    "lat": -3.130216,
    "lng": -60.02157700000001,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/45744787.jpg"
  },
  {
    "lat": -7.044324,
    "lng": -47.44229100000001,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/39343320.jpg"
  },
  {
    "lat": -1.476382,
    "lng": -48.470639000000006,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/47494007.jpg"
  },
  {
    "lat": -5.926927,
    "lng": -39.186693,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/55809012.jpg"
  },
  {
    "lat": -2.641122,
    "lng": -37.260474999999985,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/50409166.jpg"
  },
  {
    "lat": -5.860231,
    "lng": -35.181656000000004,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/56514551.jpg"
  },
  {
    "lat": -4.36157,
    "lng": -39.562040999999994,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/65213560.jpg"
  },
  {
    "lat": 6.143286,
    "lng": -62.760773,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/56409217.jpg"
  },
  {
    "lat": -3.237241,
    "lng": -42.93984900000001,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/69143088.jpg",
    "place_id": "629510d322296d0f556a3d8b07bd4a2db52805b8"
  },
  {
    "lat": -2.645377,
    "lng": -42.93984900000001,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/40239633.jpg"
  },
  {
    "lat": -5.389851388888889,
    "lng": -35.25532138888889,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/68898645.jpg"
  },
  {
    "lat": -2.165109,
    "lng": -55.11551299999999,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/44259055.jpg"
  },
  {
    "lat": 4.5646,
    "lng": -61.21442,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/65321816.jpg"
  },
  {
    "lat": -3.046583,
    "lng": -37.382355,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/382413.jpg"
  },
  {
    "lat": -7.703252,
    "lng": -38.15465900000001,
    "photo_file_url": "http://mw2.google.com/mw-panoramio/photos/medium/62426261.jpg"
  }
];
document.addEventListener("deviceready", function() {
  var div = document.getElementById("map_canvas");

  // Initialize the map view
  map = plugin.google.maps.Map.getMap(div);

  // Wait until the map is ready status.
  map.addEventListener(plugin.google.maps.event.MAP_READY, function() {
    map.moveCamera({
      target : mockData
    });

    var start = Date.now();
    addMarkers(map, mockData, function(markers) {
      var end = Date.now();
      alert("duration: " + ((end - start) / 1000).toFixed(1) + " seconds");
    });
  });
  function addMarkers(map, data, callback) {
    var markers = [];
    function onMarkerAdded(marker) {
      markers.push(marker);
      if (markers.length === data.length) {
        callback(markers);
      }
    }
    data.forEach(function(photo) {
      map.addMarker({
        position: {"lat": photo.lat, "lng": photo.lng},
        icon: {
          url: photo.photo_file_url,
          'size': {
            'width': 32,
            'height': 32
          }
        }

      }, onMarkerAdded);
    });
  }
});

Here are results:

npm version1.3.9

1.0 sec
v1.3.9 Master branch / commit caf6ec1099

1.0 sec
v2-beta / commit 906fc04

0.7 sec
wf9a5m75 commented 8 years ago

In the second test, all versions are faster since the Panoramio server is faster. However, v1.x and v2.x are different mechanism.

adding_marker

The npm v1.3.9 depends on the server response and the network speed.

The v1.3.9 master branch depends on the cache hit percentage.

The v2-beta access to the server in parallel and use cache data.

wf9a5m75 commented 8 years ago

So this is enough, isn't it?

Mojo90 commented 8 years ago

Yes, nice! (With murker clustering i think it would be perfect ;)

wf9a5m75 commented 8 years ago

Regarding of the marker cluster feature, I will implement in the future, but not now. I would like to be in stable the v2-beta before that.

hirbod commented 8 years ago

Hope soon

wf9a5m75 commented 8 years ago

Buy me a beer :)

Donate

hirbod commented 8 years ago

Just send you 100$ - so you can have 50 beer :)

wf9a5m75 commented 8 years ago

Thank you @Hirbod

samazary commented 8 years ago

Great work @wf9a5m75

huge +1 for clustering support

I also just sent you USD100 - so you can have 50 more beer :)

wf9a5m75 commented 8 years ago

o-pint-glass-beer-facebook @samazary Thank you

cvaliere commented 8 years ago

thank you @wf9a5m75, seems like a great upgrade I can't use it yet because it crashes immediately with Xwalk. Are you working on it, or can you give me a tip of what should be done, and I'll try to do it?

wf9a5m75 commented 8 years ago

No xwalk tested. And some method and event names are changed. I recommened you use the plugin in a new project. Don't use it in your project immediately

cvaliere commented 8 years ago

ok, so, are you working on it, or you want someone else to work on it, and then can you give me a tip of what should be done? (I suppose you know what should be done, as the current master branch supports Xwalk)

wf9a5m75 commented 8 years ago

Basically I'm not interested in XWalk, but I tried a little.

I don't know why but mapView.onCreate(null); does not work with XWalk. The below error is inside the MapView (I guess).

In that case, XWalk is not available.

Rejecting re-init on previously-failed class java.lang.Class<lz>: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/chimera/Fragment;
    at java.lang.Class dalvik.system.DexFile.defineClassNative(java.lang.String, java.lang.ClassLoader, java.lang.Object, dalvik.system.DexFile) (DexFile.java:-2)
    at java.lang.Class dalvik.system.DexFile.defineClass(java.lang.String, java.lang.ClassLoader, java.lang.Object, dalvik.system.DexFile, java.util.List) (DexFile.java:299)
    at java.lang.Class dalvik.system.DexFile.loadClassBinaryName(java.lang.String, java.lang.ClassLoader, java.util.List) (DexFile.java:292)
    at java.lang.Class dalvik.system.DexPathList.findClass(java.lang.String, java.util.List) (DexPathList.java:418)
    at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:54)
    at java.lang.Class com.google.android.chimera.container.internal.DelegateLastPathClassLoader.loadClass(java.lang.String, boolean) (:com.google.android.gms:28)
    at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312)
    at maps.ad.as maps.ad.aw.a(android.content.Context, maps.y.J, maps.ad.ax, java.lang.String, boolean) ((null):0)
    at maps.ad.t maps.ad.t.a(com.google.android.gms.maps.GoogleMapOptions, boolean, maps.ad.c) ((null):0)
    at void maps.ad.R.a(android.os.Bundle) ((null):-1)
    at boolean wg.onTransact(int, android.os.Parcel, android.os.Parcel, int) (:com.google.android.gms.DynamiteModulesB:66)
    at boolean android.os.Binder.transact(int, android.os.Parcel, android.os.Parcel, int) (Binder.java:499)
    at void com.google.android.gms.maps.internal.IMapViewDelegate$zza$zza.onCreate(android.os.Bundle) ((null):-1)
    at void com.google.android.gms.maps.MapView$zza.onCreate(android.os.Bundle) ((null):-1)
    at void com.google.android.gms.dynamic.zza$3.zzb(com.google.android.gms.dynamic.LifecycleDelegate) ((null):-1)
    at void com.google.android.gms.dynamic.zza$1.zza(com.google.android.gms.dynamic.LifecycleDelegate) ((null):-1)
    at void com.google.android.gms.maps.MapView$zzb.zzbru() ((null):-1)
    at void com.google.android.gms.maps.MapView$zzb.zza(com.google.android.gms.dynamic.zzf) ((null):-1)
    at void com.google.android.gms.dynamic.zza.zza(android.os.Bundle, com.google.android.gms.dynamic.zza$zza) ((null):-1)
    at void com.google.android.gms.dynamic.zza.onCreate(android.os.Bundle) ((null):-1)
    at void com.google.android.gms.maps.MapView.onCreate(android.os.Bundle) ((null):-1)
    at void plugin.google.maps.PluginMap$1.run() (PluginMap.java:223)
hirbod commented 8 years ago

Just giving my 2 cents on it: you might not be interested, but Cordova without Xwalk is a big piece of unusable shit. Xwalk=the same web view for every android device. The only real way to provide a good working app. So please don't ignore Xwalk

wf9a5m75 commented 8 years ago

Move your hands, please. Although I'm not interested in XWalk, but I'm not leave it completely. However I have no solution at this time.

So please move your hands to solve the issue. Thanks.

dsemerida commented 7 years ago

i have implement this code to render markers with the beta 2 map , according the result of this is on 1.0 secunds with the map beta 2 but on my project are 4.2 secunds ago, i dont idea, i have clone the beta 2 project and set cordova prepare but the time is the same

var map;
var mockData = [
  {
      lat: "-23.548922600000000",
      lng: "-46.574610800000000",
  },
  {
      lat: "-23.549337900000000",
      lng: "-46.574795600000000",
  },
  {
      lat: "-23.550828933700000",
      lng: "-46.576023101800000",
  },
  {
      lat: "-23.550889500000000",
      lng: "-46.576046300000000",
  },
  {
      lat: "-23.551199100000000",
      lng: "-46.575804400000000",
  },
  {
      lat: "-23.550761500000000",
      lng: "-46.575932700000000",
  },
  {
      lat: "-23.550820100000000",
      lng: "-46.575986100000000",
  },
  {
      lat: "-23.550958200000000",
      lng: "-46.576498800000000",
  },
  {
      lat: "-23.550552368200000",
      lng: "-46.574832916300000",
  },
  {
      lat: "-23.550529480000000",
      lng: "-46.575012207000000",
  },
  {
      lat: "-23.549200058000000",
      lng: "-46.573200225800000",
  },
  {
      lat: "-23.549949646000000",
      lng: "-46.572673797600000",
  },
  {
      lat: "-23.550093900000000",
      lng: "-46.572460600000000",
  },
  {
      lat: "-23.550067000000000",
      lng: "-46.572427400000000",
  },
  {
      lat: "-23.549314300000000",
      lng: "-46.571722400000000",
  },
  {
      lat: "-23.548916800000000",
      lng: "-46.572370800000000",
  },
  {
      lat: "-23.550040200000000",
      lng: "-46.571646100000000",
  },
  {
      lat: "-23.551219500000000",
      lng: "-46.571387300000000",
  },
  {
      lat: "-23.550374984700000",
      lng: "-46.571079254200000",
  },
  {
      lat: "-23.551379900000000",
      lng: "-46.572379600000000",
  },
  {
      lat: "-23.551279068000000",
      lng: "-46.571372985800000",
  },
  {
      lat: "-23.550819700000000",
      lng: "-46.571475300000000",
  },
  {
      lat: "-23.550776800000000",
      lng: "-46.571910200000000",
  },
  {
      lat: "-23.551599502600000",
      lng: "-46.575599670400000",
  },
  {
      lat: "-23.551599502600000",
      lng: "-46.575599670400000",
  },
  {
      lat: "-23.552324295000000",
      lng: "-46.575397491500000",
  },
  {
      lat: "-23.551766600000000",
      lng: "-46.575586100000000",
  },
  {
      lat: "-23.551599502600000",
      lng: "-46.575599670400000",
  },
  {
      lat: "-23.552499771100000",
      lng: "-46.574798584000000",
  },
  {
      lat: "-23.552565800000000",
      lng: "-46.574789700000000",
  },
  {
      lat: "-23.552565800000000",
      lng: "-46.574789700000000",
  },
  {
      lat: "-23.551799774200000",
      lng: "-46.573898315400000",
  },
  {
      lat: "-23.551788330100000",
      lng: "-46.574462890600000",
  },
  {
      lat: "-23.551799774200000",
      lng: "-46.573898315400000",
  },
  {
      lat: "-23.553100585900000",
      lng: "-46.575500488300000",
  },
  {
      lat: "-23.553400039700000",
      lng: "-46.575199127200000",
  },
  {
      lat: "-23.553100500000000",
      lng: "-46.574628900000000",
  },
  {
      lat: "-23.552700042700000",
      lng: "-46.573799133300000",
  },
  {
      lat: "-23.553236007700000",
      lng: "-46.574249267600000",
  },
  {
      lat: "-23.553236007700000",
      lng: "-46.574249267600000",
  },
  {
      lat: "-23.552700042700000",
      lng: "-46.573799133300000",
  },
  {
      lat: "-23.553236007700000",
      lng: "-46.574249267600000",
  },
  {
      lat: "-23.552421900000000",
      lng: "-46.573419800000000",
  },
  {
      lat: "-23.552553176900000",
      lng: "-46.573181152300000",
  },
  {
      lat: "-23.552079300000000",
      lng: "-46.572764700000000",
  },
  {
      lat: "-23.552452087400000",
      lng: "-46.573001861600000",
  },
  {
      lat: "-23.552553176900000",
      lng: "-46.573181152300000",
  },
  {
      lat: "-23.552080154400000",
      lng: "-46.572765350300000",
  },
  {
      lat: "-23.552339553800000",
      lng: "-46.571506500200000",
  },
  {
      lat: "-23.552373800000000",
      lng: "-46.571509900000000",
  },
  {
      lat: "-23.551967620800000",
      lng: "-46.571239471400000",
  },
  {
      lat: "-23.553024292000000",
      lng: "-46.572566986100000",
  },
  {
      lat: "-23.553100585900000",
      lng: "-46.572799682600000",
  },
  {
      lat: "-23.553188324000000",
      lng: "-46.573322296100000",
  },
  {
      lat: "-23.553508758500000",
      lng: "-46.573505401600000",
  },
  {
      lat: "-23.552674900000000",
      lng: "-46.573789000000000",
  },
  {
      lat: "-23.552713600000000",
      lng: "-46.573731100000000",
  },
  {
      lat: "-23.553152200000000",
      lng: "-46.571818300000000",
  },
  {
      lat: "-23.553367614700000",
      lng: "-46.571437835700000",
  },
  {
      lat: "-23.553100585900000",
      lng: "-46.571701049800000",
  },
  {
      lat: "-23.553808212300000",
      lng: "-46.571708679200000",
  },
  {
      lat: "-23.553110600000000",
      lng: "-46.571771400000000",
  },
  {
      lat: "-23.553100585900000",
      lng: "-46.571701049800000",
  }
];
document.addEventListener("deviceready", function() {
  var div = document.getElementById("map_canvas");

  // Initialize the map view
  map = plugin.google.maps.Map.getMap(div);

  // Wait until the map is ready status.
  map.addEventListener(plugin.google.maps.event.MAP_READY, function() {
    map.moveCamera({
      target : mockData
    });

    var start = Date.now();
    addMarkers(map, mockData, function(markers) {
      var end = Date.now();
      alert("duration: " + ((end - start) / 1000).toFixed(1) + " seconds");
    });
  });
  function addMarkers(map, data, callback) {
    var markers = [];
    function onMarkerAdded(marker) {
      markers.push(marker);
      if (markers.length === data.length) {
        callback(markers);
      }
    }
    data.forEach(function(position) {
      map.addMarker({
        position: position,
        icon: {
          url: "http://googlemaps.googlermania.com/img/google-marker-big.png",
          'size': {
            'width': 30,
            'height': 52
          }
        }

      }, onMarkerAdded);
    });
  }
});
wf9a5m75 commented 7 years ago

I have no idea.

guillenotfound commented 7 years ago

As response to @dsemerida : Point 5 -> https://github.com/mapsplugin/v2.0-demo/issues/6#issuecomment-253334483

Also noticed this, but I didn't have so much time to deeply investigate it, I'd like to create a sample project with +300 markers and measure the time between 1.4 and 2.0

alexbonhomme commented 7 years ago

Hey!

First, thanks for your job, this plugin is awesome :-)

I used the v1 (with Ionic 1) on my app and I'm currently writing a new version using Ionic 2 and the v2 of the plugin. Everything is fine except the markers creation. I add 222 markers on my map. The v1 handle it without problem, but the v2 is extremely slow on Android :-(

~1.5s on this project (v1) : https://github.com/alexetmanon/vliller ~10s on this project (v2) : https://github.com/alexetmanon/vliller2

I make a test repo here : https://github.com/blckshrk/addmarker-debug On my Nexus 5 it takes ~1.5s to add 100 markers and ~5s with 200 markers.

I have no idea from where it can come from... Should it be the Android SDK ? Is 200 markers a lot (it seems not on the v1) ? I've tried every thing, but really, I don't get it.

Could you take a look ? :-)