web-dev-qa-db-fra.com

Problèmes avec les onglets de l'interface utilisateur de Google Maps API v3 + jQuery

Il existe un certain nombre de problèmes, qui semblent assez bien connus, lors de l'utilisation de l'API Google Maps pour rendre une carte dans un onglet d'interface utilisateur jQuery. J'ai vu SO questions postées sur des problèmes similaires ( ici et ici , par exemple) mais les solutions ne semblent fonctionner que pour v2 de l'API Maps. Les autres références que j'ai consultées sont ici et ici , avec à peu près tout ce que je pouvais creuser via Google.

J'ai essayé de bourrer une carte ( en utilisant la v3 de l'API ) dans un onglet jQuery avec des résultats mitigés. J'utilise les dernières versions de tout (actuellement jQuery 1.3.2, jQuery UI 1.7.2, je ne connais pas Maps).

Voici le balisage et javascript:

<body>
    <div id="dashtabs">
        <span class="logout">
            <a href="go away">Log out</a>
        </span>
        <!-- tabs -->
        <ul class="dashtabNavigation">
            <li><a href="#first_tab" >First</a></li>
            <li><a href="#second_tab" >Second</a></li>
            <li><a href="#map_tab" >Map</a></li>
        </ul>

        <!--  tab containers -->
        <div id="first_tab">This is my first tab</div>
        <div id="second_tab">This is my second tab</div>
        <div id="map_tab">
             <div id="map_canvas"></div>
        </div>
    </div>
</body>

et

$(document).ready(function() {
    var map = null;
    $('#dashtabs').tabs();
    $('#dashtabs').bind('tabsshow', function(event, ui) {
        if (ui.panel.id == 'map_tab' && !map)
        {
            map = initializeMap();
            google.maps.event.trigger(map, 'resize');
        }
    });
});

function initializeMap() {
    // Just some canned map for now
    var latlng = new google.maps.LatLng(-34.397, 150.644);
    var myOptions = {
        zoom: 8,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    return new google.maps.Map($('#map_canvas')[0], myOptions);
}

Et voici ce que j'ai trouvé qui fonctionne/ne fonctionne pas ( pour Maps API v3):

  • L'utilisation de la technique à gauche décrite dans la documentation des onglets jQuery UI (et dans les réponses aux deux questions que j'ai liées) ne fonctionne pas du tout. En fait, le code qui fonctionne le mieux utilise le CSS .ui-tabs .ui-tabs-hide { display: none; } À la place.
  • La seule façon d'obtenir une carte à afficher dans un onglet est de définir la largeur et la hauteur CSS de #map_canvas En valeurs absolues. Si vous changez la largeur et la hauteur en auto ou 100%, La carte ne s'affichera pas du tout, même si elle a déjà été correctement affichée (en utilisant la largeur et la hauteur absolues).
  • Je n'ai pu le trouver documenté nulle part en dehors de l'API Maps, mais map.checkResize() ne fonctionnera plus. Au lieu de cela, vous devez déclencher un événement de redimensionnement en appelant google.maps.event.trigger(map, 'resize').
  • Si la carte n'est pas initialisée à l'intérieur d'une fonction liée à un événement tabsshow, la carte elle-même est rendue correctement mais les contrôles ne le sont pas - la plupart sont simplement manquants.

Donc, voici mes questions:

  • Quelqu'un d'autre a-t-il de l'expérience pour accomplir ce même exploit? Dans l'affirmative, comment avez-vous déterminé ce qui fonctionnerait réellement, car les astuces documentées ne fonctionnent pas pour l'API Maps v3?
  • Qu'en est-il du chargement du contenu des onglets à l'aide d'Ajax selon les documents jQuery UI ? Je n'ai pas eu l'occasion de jouer avec, mais je suppose que cela va encore plus casser Maps. Quelles sont les chances de le faire fonctionner (ou cela ne vaut-il pas la peine d'essayer)?
  • Comment faire pour que la carte remplisse la plus grande zone possible? Je voudrais qu'il remplisse l'onglet et s'adapte aux redimensionnements des pages, de la même manière que cela se fait sur maps.google.com. Mais, comme je l'ai dit, il me semble que je ne peux appliquer que CSS de largeur et de hauteur absolues au div de la carte.

Désolé si cela a été de longue haleine, mais cela pourrait être la seule documentation pour les onglets Maps API v3 + jQuery. À votre santé!

70
Matt Ball

Remarque: cette réponse a reçu une modification tierce non valide qui a essentiellement remplacé son contenu, ce qu'un éditeur tiers ne devrait pas faire. Cependant, le résultat peut être plus utile que l'original, donc les deux versions sont maintenant données ci-dessous:


  • Version originale de l'auteur Anon de 2010, après une édition par Anon

    google.maps.event.trigger (carte, "redimensionner"); map.setZoom (map.getZoom ());

est suggéré par http://code.google.com/p/gmaps-api-issues/issues/detail?id=1448 comme substitut v3 de checkResize () de v2.

Blech - mauvais google, pas de cookie.


  • Formulaire de réécriture complet 2012 de l'utilisateur Eugeniusz Fizdejko:

Pour moi, cela fonctionne lors de l'ajout d'un marqueur:

var marker = new google.maps.Marker({
    position: myLatlng,
    title:"Hello World!"
});

google.maps.event.addListener(map, "idle", function(){
    marker.setMap(map);
});
22
Anon

En fait, grattez ma réponse ci-dessus. Le site Web jQueryUI a la réponse et la voici:

Pourquoi ...

... mon curseur, Google Map, sIFR etc. ne fonctionnent pas lorsqu'ils sont placés dans un onglet caché (inactif)?

Tout composant qui nécessite un calcul dimensionnel pour son initialisation ne fonctionnera pas dans un onglet masqué, car le panneau à onglets lui-même est masqué via l'affichage: aucun de sorte que les éléments à l'intérieur ne rapportent pas leur largeur et hauteur réelles (0 dans la plupart des navigateurs) .

Il existe une solution de contournement facile. Utilisez la technique à gauche pour masquer les panneaux à onglets inactifs. Par exemple. dans votre feuille de style remplacez la règle pour le sélecteur de classe ".ui-tabs .ui-tabs-hide" par

.ui-tabs .ui-tabs-hide {
    position: absolute;
    left: -10000px;
}

Pour Google maps, vous pouvez également redimensionner la carte une fois l'onglet affiché comme ceci:

$('#example').bind('tabsshow', function(event, ui) {
    if (ui.panel.id == "map-tab") {
        resizeMap();
    }
});

resizeMap () appellera checkResize () de Google Maps sur la carte particulière.

13
jeffkee

Redéfinissez simplement la classe css pour l'onglet caché:

.ui-tabs .ui-tabs-hide {
    position: absolute !important;
    left: -10000px !important;
    display:block !important;
}
12
memberyh

Voici ce que vous pouvez faire pour Google Maps v3:

google.maps.event.addListenerOnce(map, 'idle', function() {
    google.maps.event.trigger(map, 'resize');
    map.setCenter(point); // be sure to reset the map center as well
});
9
jayarjo

Je charge les cartes une fois l'onglet affiché.

C'est hacky mais ça a marché pour moi. Stockez simplement l'url de la carte iframe dans l'attribut rel iframes comme ceci:

<iframe width="490" height="300" rel="http://maps.google.com/maps?f=q&amp;source=s..."></iframe>

Cet événement définira l'attribut iframe src sur l'URL à l'intérieur de la rel.

        $("#tabs").tabs({
            show:function(event, ui) {
                var rel = $(ui.panel).find('iframe').attr('rel');
                $(ui.panel).find('iframe').attr('src',rel);
            }
        });
4
Keyo

Cela ne répond pas à toutes vos questions, mais je l'ai fait fonctionner et toutes les autres réponses manquent une chose - lorsque vous redessinez la carte avec l'événement "resize", vous perdrez l'endroit sur lequel la carte était centrée. Vous devez donc également mettre à jour le centre de la carte avec setCenter, si votre carte est centrée sur une position.

De plus, vous ne voulez pas initialiser la carte chaque fois que le changement d'onglet est déclenché, car cela n'est pas efficace et peut entraîner des géocodes supplémentaires. Tout d'abord, vous devez enregistrer votre emplacement centré, qui peut être un lat/long statique, ou si le géocodage, peut ressembler à ceci:

var address = "21 Jump St, New York, NY"; 
var geocoder = new google.maps.Geocoder();    
var myOptions = {
  zoom: 16,      
  mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

var center;

geocoder.geocode( { 'address': address}, function(results, status) {
  if (status == google.maps.GeocoderStatus.OK) {        
    center = results[0].geometry.location;
    map.setCenter(center);
    var marker = new google.maps.Marker({
        map: map, 
        position: results[0].geometry.location
    });
  } else {
    alert("Geocode was not successful for the following reason: " + status);
  }
});

Ensuite

$("#tabs").tabs();

$('#tabs').bind('tabsshow', function(event, ui) {
    if (ui.panel.id == "mapTab") {
        google.maps.event.trigger(map, "resize");
        map.setCenter(center);   // Important to add this!      
    }
});

Où "mapTab" est l'ID de votre mapTab et "map" est le nom var de votre objet map.

4
paul

Assurez-vous que le code qui initialise votre carte s'appelle AVANT l'extrait de code qui initialise vos onglets.

Les seuls ennuis que j'ai eus ont été qu'un clic sur l'onglet de la carte a fait sauter le navigateur pour se concentrer sur la carte et qu'il a rompu la bordure par défaut que jQuery place autour du conteneur des onglets principaux. J'ai ajouté un appel false onclick de retour à la balise de l'onglet carte pour gérer le premier et une taille de bordure simple: 0 sur la div des onglets principaux pour gérer le second.

Tout cela a fonctionné pour moi.

Bonne chance!

2
Vaughn

J'ai parcouru tous les forums à la recherche de la réponse à cela ... ils ont tous dit d'utiliser le

map.checkResize()

solution .... rien ne semblait fonctionner ... alors je ... pourquoi ne pas initialiser l'onglet lorsque l'onglet est affiché donc j'ai utilisé cela

$("#servicesSlider ").tabs({        
                //event: 'mouseover'
            fx: { height: 'toggle', opacity: 'toggle'},
            show: function(event, ui) {
                  if (ui.panel.id == "service5") {
                      $(ui.panel).css("height","100%")
                    initialize()
                    }}
            });

"service5" est l'identifiant de mon onglet qui contient ma carte google map v3.

J'espère que cela fonctionne pour toi!

1
Dave

J'ai aussi eu ce problème, je chargeais les cartes via AJAX.

Il semble que le problème avec le pourcentage soit dû au fait que le panneau n'a pas de taille définie (celui contenant le balisage chargé).

L'utilisation du code suivant lors de la création des onglets m'a beaucoup aidé:

$("#mainTabs").tabs({'show': function(event, ui){
  $(ui.panel).attr('style', 'width:100%;height:100%;');
  return true;
 }});
1
Andy

Hé les gars, ce code corrige l'erreur mais dans IE ne fonctionne pas. Après avoir cherché et recherché, j'ai découvert que nous devons ajouter la ligne suivante et tout fonctionne à la perfection:

< !--[if IE]>
< style type="text/css">
.ui-tabs .ui-tabs-hide { position: relative; }
< /style>
< ![endif]-->
1
Andrés Sepúlveda

J'ai obtenu cela fonctionnant facilement en chargement asynchrone de l'API puis en appelant simplement loadScript à partir du <a> tag lié à l'onglet correspondant de l'événement onclick comme ceci:

<li><a href="#tab3" onclick="loadScript();">Maps</a></li>
0
keithxm23

Tu peux appeler

map.fitBounds (limites)

qui fera le rafraîchissement

0
Juan arce

Problème très irritant mais avec un peu de hackaround c'est réparable. La clé est de faire en sorte que la position relative #tabs s'ajuste à la hauteur extérieure de chacun des onglets lorsque vous en sélectionnez un nouveau. Voici comment je l'ai fait:

$('#tabs').tabs({
   selected:0,
   'select': function(event, ui) {
    //this is the href of the tab you're selecting
    var currentTab = $(ui.tab).attr('href');
    //this is the height of the related tab plus a figure on the end to account for padding...
    var currentInner = $(currentTab + '.detail-tab').outerHeight() + 40;
    //now just apply the height of the current tab you're selecting to the entire position:relative #tabs ID
    $('#tabs').css('height', currentInner);
   }
  });

voici le css que j'ai utilisé:

#tabs { position: relative; }
/*set the width here to whatever your column width is*/
.ui-tabs-panel{ position:absolute;top:0px; left:0; width:575px;}
.ui-tabs-panel.ui-tabs-hide { display:block !important; position:absolute;  left:-99999em; top:-9999em}
0
Tom Gordon

J'étais confronté au même problème dans Semantic UI, Le problème a été résolu lors de l'appel de la fonction init(); lorsqu'un onglet se charge ou vous pouvez également le lier.

0
Moxet Khan

J'ai fait ce que dit Keith et cela fonctionne pour moi, dans mon cas, j'utilise des waypoints jQuery pour ma navigation par onglets, pour une meilleure compréhension, voici le code que j'ai utilisé:

Dans la tête

<head>

<!-- Google Maps -->
<script>
function initialize() {
  var mapOptions = {
    zoom: 8,
    center: new google.maps.LatLng(-34.397, 150.644)
  };

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

function loadScript() {
  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.src = 'https://maps.googleapis.com/maps/api/js?v=3.exp' + '&signed_in=true&callback=initialize';
  document.body.appendChild(script);
}
window.onload = loadScript;
</script>

</head>

À l'intérieur de mes onglets:

<li><a href="#MyMap" onclick="loadScript();">My Map</a></li>

Puis dans la DIV

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

J'espère que cela aide quelqu'un, merci pour tous!

0
yehanny

Une autre solution pour Maps API v3 (exp) et jQuery UI 1.10:

var pano = new google.maps.StreetViewPanorama(...);

$('#tabs').tabs({
  'activate': function(event, ui) {
    if (ui.newPanel[0].id == "maps-tabs-id") {
      pano.setVisible(true);
    }
  }
});
0
Wernight

J'ai eu le même problème et aucune des réponses n'a fonctionné pour moi. Peut-être que je ne savais pas comment les utiliser dans mon code, j'ai donc ajouté un événement onclick au menu de l'onglet pour initialiser Google map et cela fonctionne. Je ne sais pas si c'est une bonne pratique cependant.

jQuery(document).ready(function($) {
$( '#tabs' ).tabs();
var href = $('#tabs').find('a[href="#tabs-4"]');
(href).on('click',function(){
    initialize();
})});
var map;
function initialize() {
  var mapOptions = {
    zoom: 8,
    center: new google.maps.LatLng(-34.397, 150.644),
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  map = new google.maps.Map(document.getElementById('map'),
      mapOptions);
}

<div id="tabs-4">
    <div id="map" style="width:580px;height:380px;">
    </div>
</div>
0
arjang27