5 votes

Google Map API BackBoneJS Impossible de lire la propriété 'offsetWidth' de null

J'ai parcouru autant de groupes StackOverflow/google que je peux imaginer pour essayer de comprendre ce type.

J'utilise BackboneJS pour rendre une carte qui a un emplacement de départ et un emplacement d'arrivée. Lors d'un rafraîchissement de la page, je n'obtiens pas cette erreur, et la carte et les autres éléments fonctionnent correctement, car j'utilise la fonction jQuery $(window).load(.....) ; cependant, lorsque je rends dynamiquement ma vue, j'obtiens cette erreur - je crois - parce que le DOM n'a pas encore chargé le DIV (échec avec document.getElementById). J'ai essayé toutes sortes de méthodes différentes autres que $(window).load(), mais je n'arrive pas à obtenir quelque chose qui fonctionne pour les deux cas d'utilisation (chargement d'une nouvelle page -- chargement d'une vue BackboneJS). Essayer d'appeler la fonction juste après le template ne fonctionne pas non plus.

Toute aide serait appréciée.

Robert

Vue :

    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>

7voto

mu is too short Points 205090

Je suppose que votre problème est le suivant #mapCanvas n'est pas dans le DOM jusqu'à ce que vous essayiez d'y accéder :

document.getElementById('mapCanvas')

vous donnera une null . Vous devez attendre jusqu'à ce que #mapCanvas est dans le DOM avant de l'utiliser ; vous ne pouvez pas non plus faire quelque chose comme ça :

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

Vous obtiendrez ainsi un identifiant valide, mais vous troublerez les fonctions de Google Maps, car l'identifiant n'aura pas de taille et la carte sera affichée de manière étrange. Cela vous ramène à attendre que tout soit dans le DOM avant de lier vos fonctions Google Maps.

Une façon de contourner ce problème est d'utiliser setTimeout avec un délai de zéro :

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

Cela semble étrange, mais cela fonctionne, cette astuce permet de décharger votre renderMap dans la file d'attente du navigateur et il l'exécutera une fois que vous aurez rendu le contrôle au navigateur.

Vous pouvez également utiliser _.defer :

reporter _.defer(function, [*arguments])

Diffère l'invocation de la fonction fonction jusqu'à ce que la pile d'appels en cours soit vidée, ce qui est similaire à l'utilisation de setTimeout avec un délai de 0. Utile pour effectuer des calculs coûteux ou un rendu HTML par morceaux sans bloquer la mise à jour du fil d'exécution de l'interface utilisateur.

Il s'agit d'un meilleur choix, car il rend votre intention explicite.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X