2012-08-12 22 views
5

He pasado por tantos grupos de StackOverflow/google como puedo imaginar tratando de resolver este tipo.Google Map API BackBoneJS No se puede leer la propiedad 'offsetWidth' de nulo

Estoy usando BackboneJS para renderizar un mapa que tiene una ubicación de inicio y una ubicación final. En una nueva actualización de página/página, no obtengo este error, y el mapa y las cosas funcionan bien, porque estoy usando la función $ (ventana) .load (.....) de jQuery; sin embargo, cuando visualizo dinámicamente mi Vista, obtengo este error, creo, porque el DOM aún no ha cargado el DIV (fallando con document.getElementById). He intentado todo tipo de métodos diferentes a $ (window) .load(), pero no puedo obtener nada que funcione para ambos casos de uso (carga de página nueva - carga de la vista de BackboneJS). Intentar llamar a la función justo después de que la plantilla no funcione tampoco.

Cualquier ayuda sería apreciada.

Robert

Vista:

App.Views.MapShow = Backbone.View.extend({ 
     initialize: function() { 
     _.bindAll(this, 'render'); 
     var self = this; 
     $(window).load(function() { 
      self.renderMap(); 
     }); 
     }, 

     render: function() { 
     this.renderTemplate(); 
     }, 

     renderTemplate: function() { 
     this.$el.html(JST['path/to/show/file']()); 
     }, 

     renderMap: function() { 
     var from  = this.model.get('location_from'); 
     var to  = this.model.get('location_to'); 
     var geocoder = new google.maps.Geocoder(); 
     var map  = new google.maps.Map(document.getElementById('mapCanvas'), { 
      mapTypeId: google.maps.MapTypeId.ROADMAP 
     }); 
     var directionsService = new google.maps.DirectionsService(); 
     var directionsDisplay = new google.maps.DirectionsRenderer(); 

     directionsDisplay.setMap(map); 

     var request = { 
      origin: from, 
      destination: to, 
      travelMode: google.maps.DirectionsTravelMode.DRIVING 
     }; 

     directionsService.route(request, function(response, status) { 
      if (status == google.maps.DirectionsStatus.OK) { 
      directionsDisplay.setDirections(response); 
      } 
     }); 
     } 
    }); 

HTML:

<div class="map" id="mapCanvas"></div> 
+0

¿Has intentado poner el material del mapa dentro de una llamada 'setTimeout (function() {...}, 0)'? http://stackoverflow.com/a/9145790/479863 –

+0

Si no te importa poner esto como una respuesta que sería genial. Se corrigió – rpearce

+0

Refactorizado a Underscore's _.diferir función basada en la recomendación de un amigo. – rpearce

Respuesta

7

supongo que su problema es que no es #mapCanvas en el DOM hasta después de intentar acceder a él así que esto:

document.getElementById('mapCanvas') 

le dará un inútil null. Debe esperar hasta que #mapCanvas esté en el DOM antes de usarlo; no se puede hacer algo como esto ya sea:

map_canvas = this.$el.find('#mapCanvas')[0]; 

que le dará una identificación válida pero vas a confundir las funciones de mapas de Google, ya que no tendrá un tamaño por lo que el mapa se vuelve extraña. Esto lo lleva a esperar que todo esté en el DOM antes de enlazar sus cosas de Google Maps.

Una forma de evitar esto es utilizar setTimeout with a delay of zero:

var _this = this; 
setTimeout(function() { _this.renderMap() }, 0); 

Esto parece poco extraño que hace el trabajo, este truco básicamente vuelca su llamada renderMap en cola de trabajo del navegador y que va a moverse a correr una vez devolvió el control al navegador.

También puede utilizar _.defer:

Defer_.defer(function, [*arguments])

posterga invocar la funciónhasta que la pila de llamadas actual ha aclarado, similar al uso de setTimeout con un retraso de 0. Útil para realizar cálculos costosos o procesamiento de HTML en fragmentos sin bloquear el hilo de UI de la actualización.

Esta podría ser una mejor opción ya que hace que su intento sea explícito.

+0

eres el hombre. Gracias un montón – rpearce

Cuestiones relacionadas