8

Working on a Google Map app built with AngularJS.

Currently deployed sandbox: http://of.xchg.com/

Click Map link and you will notice only ONE tile IF ANY are rendered.

If you then RESIZE the browser window, THEN the rest of the map tiles will render completely.

Here is the git project: https://github.com/LarryEitel/of4

Why are not all Google Map Tiles rendered?

Is there a way to test for complete rendering of tiles?

Is there a way to force re-rendering of all map tiles?

Larry Eitel
  • 1,397
  • 5
  • 19
  • 37

3 Answers3

13

Call this function in your map controller:

google.maps.event.trigger(map, 'resize');

That should do the trick.

jesal
  • 7,852
  • 6
  • 50
  • 56
  • Thank you for your reply. Minor detail is that in order to retain map state, I inject GoogleMap as a service into the main controller. Then I show/hide as needed. The initial view has the map hidden. Ideally, would be nice to inject initialized map into MainController only on FIRST 'showing' of the map. Here is a link to the code so far: http://goo.gl/8ClMo – Larry Eitel May 02 '13 at 22:39
  • I see that in your code (in app.js) you are setting MainCtrl as the controller even for views/map.html. If you change that to MapCtrl I think that should give you the desired separation of concerns that you are looking for. Then you only need to inject GoogleMap service into the Map controller and call that resize trigger in that controller instead of the MainCtrl. – jesal May 02 '13 at 22:49
  • Made your suggested change with same behavior. Of interest is that if I do a hard refresh on /#/map, I get NO map... even after I resize browser. – Larry Eitel May 02 '13 at 23:01
  • Hm strange, I see you already have angular-ui in your components dir, so I'd suggest going with their GoogleMaps directive, it would be much easier to work with. – jesal May 03 '13 at 00:45
  • Although it may be more advantageous to use the angular-ui GoogleMaps directive, I would like to understand the reason for this behavior. – Larry Eitel May 03 '13 at 17:22
  • When I called google.maps.event.trigger(map, 'resize'); in firebug console, it worked as expected. So that leads me to believe there is an issue with GoogleMap.win[0] part. – jesal May 03 '13 at 18:43
  • It's beautiful!! You have an idea where I can call `google.maps.event.trigger(map, 'resize');` somewhere in the code once after app is initially loaded/run? In other words, just by-pass the `GoogleMap.win[0]...` call? – Larry Eitel May 04 '13 at 00:08
  • Have you tried calling it in the MapCtrl without GoogleMap.win[0] part? That would be the best place for it. – jesal May 04 '13 at 00:33
2

I found this problem when trying to re-center the map after the view loaded. There would be a single tile in the top left corner.

I noticed that it was centering the map at the topleft of the div (0,0), and figured that it must be measuring the div before it was visible. This would mean the dimensions were 0px, 0px and so to center the map would mean placing a single tile at (0,0).

I tried the solution of triggering the resize event

google.maps.event.trigger(map, 'resize');

and that almost worked - it filled the div with tiles, but it was still centered at (0,0).

What worked was to wrap the re-center code in a $timeout(). This ensures that the div is fully loaded and correctly sized before the code runs. Now it works perfectly.

$timeout(function() {
    // still need this.
    google.maps.event.trigger(map, 'resize');   
    map.setCenter(53, -6);
});
Owen O Byrne
  • 417
  • 3
  • 10
  • +1, buuuuut - is a timer a good idea? Too short & it won't work. Too long & the user sees a weird map for a while. It would be better to do this based on an event. Other plain JS answers suggest `google.maps.event.addListener(map, "idle", function()../` but I am too n00b to translate this into angular. – Mawg says reinstate Monica May 10 '14 at 06:42
  • @Mawg with a normal timer I'd agree with you, but the $timeout function in angular works a little differently when called with a zero or null time out. It runs the function in the next 'tick' of the angular code - as soon as possible after the currently running set of code. I usually use this to delay running code until just after the view has completed. (I'm open to correction on my interpretation of this! ) – Owen O Byrne May 10 '14 at 16:03
0

After a lot of trial and error, I found a workaround. By merely injecting the GoogleMap Service into the app run command, it successfully rendered the complete map. I ALSO had to make the default '/' route show the map page. Anything else I would do that involved trying to switch from a home (non-map) page to the map page would result in a partially rendered map. :(

Perhaps I or someone will suggest a more elegant solution. :)

  // Generated by CoffeeScript 1.6.1
  (function() {
    'use strict';
    angular.module('of4App', []).config(function($routeProvider) {
      return $routeProvider.when('/menu', {
        templateUrl: 'views/menu.html',
        controller: 'MainCtrl'
      }).when('/list', {
        templateUrl: 'views/list.html',
        controller: 'MainCtrl'
      }).when('/map', {
        templateUrl: 'views/map.html',
        controller: 'MapCtrl'
      }).when('/about', {
        templateUrl: 'views/main.html',
        controller: 'MainCtrl'
      }).otherwise({
        redirectTo: '/map'
      });
    }).run(function($rootScope, $location, GoogleMap) {
      var rootScope;
      rootScope = $rootScope;
      rootScope.navBarHeight = 40;
      return rootScope.mapShown = function() {
        var mapShown;
        mapShown = $location.path().indexOf('/map') > -1;
        return mapShown;
      };
    });

  }).call(this);
Larry Eitel
  • 1,397
  • 5
  • 19
  • 37
  • I asked a related question [here](http://stackoverflow.com/questions/16444095/google-map-render-events-can-they-be-watched) and @varun pointed me to a good [suggestion](http://stackoverflow.com/questions/7341769/google-maps-v3-how-to-tell-when-an-imagemaptype-overlays-tiles-are-finished-lo/7355063#7355063). – Larry Eitel May 09 '13 at 14:04