API Google MAP non capturée TypeError: impossible de lire la propriété "offsetWidth" de null

204

J'essaie d'utiliser l'API Google MAP v3 avec le code suivant.

<h2>Topology</h2>

<script src="https://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>

<link rel="stylesheet" type="text/css" href="{% url css_media 'tooltip.topology.css' %}" />
<link rel="stylesheet" type="text/css" href="{% url css_media 'tooltip.css' %}" />

<style type="text/css" >
      #map_canvas {
              width:300px;
            height:300px;
     }
</style>

<script type="text/javascript">

var latlng = new google.maps.LatLng(-34.397, 150.644);
var myOptions = {
zoom: 8,
      center: latlng,
      mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"),
            myOptions);

</script>

<div id="map_canvas"> </div>

Lorsque j'exécute ce code, le navigateur le dit.

TypeError non capturé: impossible de lire la propriété 'offsetWidth' de null

Je n'en ai aucune idée, puisque je suis la direction donnée dans ce tutoriel .

Avez-vous une idée?

jaeyong
la source

Réponses:

317

Ce problème est généralement dû au fait que le div de carte n'est pas rendu avant l'exécution du javascript qui doit y accéder.

Vous devez placer votre code d'initialisation dans une fonction de chargement ou au bas de votre fichier HTML, juste avant la balise, afin que le DOM soit complètement rendu avant son exécution (notez que la deuxième option est plus sensible aux HTML non valides).

Notez, comme le soulignent matthewsheets, cela pourrait également être dû au div avec cet identifiant qui n'existe pas du tout dans votre HTML (le cas pathologique du div n'est pas rendu)

Ajout d'un exemple de code à partir du message de wf9a5m75 pour tout mettre en un seul endroit:

<script type="text/javascript">

function initialize() {
    var latlng = new google.maps.LatLng(-34.397, 150.644);
    var myOptions = {
        zoom: 8,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    var map = new google.maps.Map(document.getElementById("map_canvas"),
            myOptions);
}
google.maps.event.addDomListener(window, "load", initialize);

</script>
géocodezip
la source
7
Cela m'arrive tout le temps quand j'oublie de conditionner mon script de cartes. Ajout: var mapExists = document.getElementById ("map-canvas"); if (mapExists) {// script} améliore tout.
Impératif
109

Pour d'autres qui pourraient encore avoir ce problème , même après avoir essayé les recommandations ci-dessus, l'utilisation d'un sélecteur incorrect pour votre canevas de carte dans la fonction d'initialisation peut provoquer ce même problème car la fonction tente d'accéder à quelque chose qui n'existe pas. Vérifiez que votre ID de carte correspond dans votre fonction d'initialisation et votre code HTML ou cette même erreur peut être levée.

En d'autres termes, assurez-vous que vos identifiants correspondent. ;)

matthewsheets
la source
3
Incroyable comment vous pouvez être si sûr que ce n'est pas le problème ... jusqu'à ce que vous revérifiez et que vous réalisiez que vous l'avez changé plus tôt en testant et oublié de le changer à nouveau. :-)
Charlie Gorichanaz
28

Vous pouvez également obtenir cette erreur si vous ne spécifiez pas centerou zoomdans vos options de carte.

JamesFrost
la source
2
C'était celui-là! Le zoom a été supprimé des options depuis que je l'ai défini plus tard dans le script, et boom, la carte se chargerait la première fois, mais la deuxième fois générerait cette erreur. Je vous remercie!!
Iain Grant
Ouais, c'était à moi! Il y avait un zoom mais pas de centre. L'ajout du centre l'a corrigé.
Whelkaholism
1
Ils auraient pu au moins enregistrer un message dans la console. Merci!
Martin Shishkov
26

google utilise id="map_canvas" et id="map-canvas"dans les exemples, revérifiez et revérifiez l'id: D

dpineda
la source
23

Année, la réponse de geocodezip est correcte. Alors changez votre code comme ceci: (si vous avez toujours des ennuis, ou peut-être quelqu'un d'autre à l'avenir)

<script type="text/javascript">

function initialize() {
    var latlng = new google.maps.LatLng(-34.397, 150.644);
    var myOptions = {
        zoom: 8,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    var map = new google.maps.Map(document.getElementById("map_canvas"),
            myOptions);
}
google.maps.event.addDomListener(window, "load", initialize);

</script>
wf9a5m75
la source
Exactement, rendez d'abord le div html, puis le JS sinon ajoutez un écouteur d'événement.
foxybagga
11

Juste pour ajouter mon scénario d'échec pour que cela fonctionne. J'avais un <div id="map>dans lequel je chargeais la carte avec:

var map = new google.maps.Map(document.getElementById("map"), myOptions);

et le div était initialement caché et il n'y avait pas explicitement de valeurs de largeur et de hauteur définies, donc sa taille était width x 0. Une fois que j'ai défini la taille de ce div en CSS comme ceci

#map {
    width: 500px;
    height: 300px;
}

tout a fonctionné! J'espère que cela aide quelqu'un.

Nikola
la source
C'est exactement la raison pour laquelle cela n'a pas fonctionné pour moi. Vous devez vous assurer que le CSS correspond à votre identifiant de carte et que vous disposez d'une sorte de combo initial largeur / hauteur, sinon rien n'est rendu. Donc, pour récapituler: 1. assurez-vous que votre identifiant div html correspond au sélecteur d'id lorsque vous appelez getElementById dans votre JavaScript 2. assurez-vous que le CSS a du code pour styliser votre carte particulière, par exemple # map1 {width: 200px; hauteur: 200px; } ou similaire pour le rendre.
Tahir Khalid
7

Pour encore plus d'autres qui pourraient encore avoir ce problème, j'utilisais une <div id="map1" />balise à fermeture automatique , et le deuxième div ne s'affichait pas et ne semblait pas être dans le dom. dès que je l'ai changé en deux balises d'ouverture et de fermeture, <div id="map1"></div>cela a fonctionné. hth

changokun
la source
6

Veillez également à ne pas écrire

google.maps.event.addDomListener(window, "load", init())

correct:

google.maps.event.addDomListener(window, "load", init)
Mike
la source
En effet. C'était aussi un problème dans mon cas. Le premier exécute la fonction init immédiatement lorsque le second passe simplement la fonction init comme paramètre à l'écouteur d'événements qui exécutera la fonction init lorsque cet événement se produit. stackoverflow.com/questions/13286233/…
kivikall
6

J'avais des guillemets simples dans mon

var map = new google.maps.Map( document.getElementById('map_canvas') );

et les a remplacés par des guillemets doubles

var map = new google.maps.Map( document.getElementById("map_canvas") );

Cela a fait l'affaire pour moi.

Programmeur VB.Net
la source
5

Changer l'ID (dans les 3 endroits) de "map-canvas" en "map" l'a corrigé pour moi, même si je m'étais assuré que les ID étaient les mêmes, la div avait une largeur et une hauteur, et le code n'était pas en cours d'exécution jusqu'à après l'appel de chargement de fenêtre. Ce n'est pas le tiret; il ne semble pas fonctionner avec un autre identifiant que "map".

Johnny5k
la source
4

Assurez-vous également que vous ne placez pas de symbole de hachage (#) dans votre sélecteur

    document.getElementById('#map') // bad

    document.getElementById('map') // good

déclaration. Ce n'est pas un jQuery. Juste un petit rappel pour quelqu'un pressé.

Keeprock
la source
3

J'ai eu le même problème, mais le problème était que le zoom n'était pas défini dans l'objet d'options donné à Google Maps.

torresomar
la source
2

Si vous créez plusieurs cartes dans une boucle, si un seul élément DOM de carte n'existe pas, il les brise toutes. Tout d'abord, vérifiez que l'élément DOM existe avant de créer un nouvel objet Map.

[...]

for( var i = 0; i <= self.multiple_maps; i++ ) {

  var map_element = document.getElementById( 'map' + '-' + i.toString() );

  // Element doesn't exist, don't create map!
  if( null === map_element ) {
    continue;
  }

  var map = new google.maps.Map( map_element, myOptions);
}

[...]
Zack Katz
la source
1
Mais tout ce que cela fait, c'est d'empêcher la création de la carte, pas de réparer le gâchis et de créer la carte.
Ryan The Leach
1

Si vous utilisez des formulaires Web asp.net et que vous enregistrez le script dans le code derrière une page à l'aide d'une page maître, n'oubliez pas d'utiliser l'ID client de l'élément de carte (vb.net):

ClientScript.RegisterStartupScript(Me.[GetType](), "Google Maps Initialization", String.Format("init_map(""" & map_canvas.ClientID() & """...
Clins d'oeil
la source
1

Pour le résoudre, vous devez ajouter async defer au script.

Cela devrait être comme ceci:

<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"
    async defer></script>

Voir ici le sens de différer asynchrone.

Puisque vous appellerez une fonction à partir du fichier js principal, vous devez également vous assurer que c'est après celle où vous chargez le script principal.

Avi Levin
la source
1

Assurez-vous d'inclure la bibliothèque des lieux &libraries=places paramètre de lors du premier chargement de l'API.

Par exemple:

<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">
Steve
la source
1

Je sais que je suis un peu en retard à la fête, je voulais juste ajouter que l'erreur peut également se produire lorsque le div n'existe pas dans la page. Vous pouvez également vérifier si le div existe avant de charger l'appel de la fonction google maps. Quelque chose comme

function initMap() {
    if($("#venuemap").length != 0) {
        var city= {lat: -26.2041, lng: 28.0473};
        var map = new google.maps.Map(document.getElementById('venuemap'), {
       etc etc
     }
}
mr_j
la source
1
  • Configurez ng-init = init () dans votre HTML
  • Et dans le contrôleur

    utilisez $ scope.init = function () {...} au lieu de google.maps.event.addDomListener (window, "load", init) {...}

J'espère que ceci vous aidera.

Akash Saxena
la source
0

En fait, le moyen le plus simple de résoudre ce problème est de déplacer votre objet avant que le code Javascript ne fonctionne. Je suppose que votre objet de réponse est chargé après le code javascript.

<style type="text/css" >
      #map_canvas {
              width:300px;
            height:300px;
     }

 <div id="map_canvas"> </div> // Here 

<script type="text/javascript">

var latlng = new google.maps.LatLng(-34.397, 150.644);
var myOptions = {
zoom: 8,
      center: latlng,
      mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"),
            myOptions);

</script>

<div id="map_canvas"> </div>
Laltzi
la source
0

Dans mon cas, ce type de problèmes a été résolu à l'aide de defer https://developer.mozilla.org/en/docs/Web/HTML/Element/script

<script src="<your file>.js" defer></script>

Vous devez cependant prendre en compte la prise en charge par les navigateurs de cette option (je n'ai pas vu de problèmes)

Yercalamarino
la source
0

Vérifiez que vous ne remplacez pas window.self

Mon problème: j'avais créé un composant et écrit self = thisau lieu de var self = this. Si vous n'utilisez pas le mot-clé var, JS mettra cette variable sur l'objet fenêtre, j'ai donc écrasé window.selfce qui a causé cette erreur.

Mike R Emo
la source
0

Il s'agit d'une modification d'une publication précédemment supprimée pour contenir le contenu de la réponse liée, dans la réponse elle-même. Le but de la republication de cette réponse est de fonctionner comme un PSA pour les utilisateurs de React 0.9+ qui sont également tombés sur ce problème.

message édité d'origine


A également obtenu cette erreur lors de l'utilisation de ReactJS tout en suivant ce billet de blog . Le commentaire de sahat ici a aidé - voir le contenu du commentaire de sahat ci-dessous.

❗️ Remarque pour React> = 0,9

Avant la v0.9, le nœud DOM était transmis comme dernier argument. Si vous l'utilisiez, vous pouvez toujours accéder au nœud DOM en appelant this.getDOMNode ().

En d'autres termes, remplacez le paramètre rootNode par this.getDOMNode () dans la dernière version de React.

Meredith
la source
0

Mon échec a été d'utiliser

zoomLevel

en option, plutôt que l'option correcte

zoom
strattonn
la source
0

ajouter un report asynchrone au début de l'appel de la clé API de la carte.

Ghadir Farzaneh
la source
0

Dans un cas que je traitais, le div de la carte a été rendu sous condition selon que l'emplacement était rendu public. Si vous ne pouvez pas être sûr que le div du canevas de carte sera sur la page, vérifiez simplement que votre document.getElementByIdretourne un élément et n'appelez la carte que si elle est présente:

var mapEle = document.getElementById("map_canvas");
if (mapEle) {
    map = new google.maps.Map(mapEle, myOptions);
}
Rillus
la source
-2

Ici, le problème était le lien API sans le keyparamètre:

<script type="text/javascript" src="http://maps.google.com/maps/api/js?libraries=places&key=YOURKEY"></script>

De cette façon, ça marche bien.

vaati
la source