Probleme mit den Registerkarten der Google Maps API v3 + jQuery-Benutzeroberfläche

70

Bei der Verwendung der Google Maps-API zum Rendern einer Karte auf einer Registerkarte der jQuery-Benutzeroberfläche gibt es eine Reihe von Problemen, die ziemlich bekannt zu sein scheinen. Ich habe SO-Fragen zu ähnlichen Problemen gesehen ( hier und hier zum Beispiel), aber die Lösungen dort scheinen nur für Version 2 der Maps-API zu funktionieren. Andere Referenzen, die ich ausgecheckt habe, sind hier und hier , zusammen mit so ziemlich allem, was ich durch Googeln ausgraben konnte.

Ich habe versucht, eine Karte ( mit Version 3 der API ) in eine jQuery-Registerkarte mit gemischten Ergebnissen zu stopfen . Ich verwende die neuesten Versionen von allem (derzeit jQuery 1.3.2, jQuery UI 1.7.2, weiß nichts über Maps).

Dies ist das Markup & 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>

und

$(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);
}

Und hier ist, was ich gefunden habe, das funktioniert / nicht funktioniert ( für Maps API v3 ):

  • Die Verwendung der Off-Left-Technik, wie in der Dokumentation zu den jQuery-UI-Registerkarten (und in den Antworten auf die beiden von mir verknüpften Fragen) beschrieben, funktioniert überhaupt nicht. Tatsächlich verwendet der am besten funktionierende Code .ui-tabs .ui-tabs-hide { display: none; }stattdessen das CSS .
  • Die einzige Möglichkeit, eine Karte überhaupt auf einer Registerkarte anzuzeigen, besteht darin, die CSS-Breite und -Höhe #map_canvasauf absolute Werte festzulegen. Durch Ändern der Breite und Höhe in autooder 100%wird die Karte überhaupt nicht angezeigt, selbst wenn sie bereits erfolgreich gerendert wurde (unter Verwendung der absoluten Breite und Höhe).
  • Ich konnte es nirgendwo außerhalb der Maps-API dokumentiert finden, map.checkResize()funktioniert aber nicht mehr. Stattdessen müssen Sie ein Größenänderungsereignis durch Aufrufen auslösen google.maps.event.trigger(map, 'resize').
  • Wenn die Karte nicht innerhalb einer an ein tabsshowEreignis gebundenen Funktion initialisiert wird , wird die Karte selbst korrekt gerendert, die Steuerelemente jedoch nicht - die meisten fehlen einfach.

Also, hier sind meine Fragen:

  • Hat jemand anderes Erfahrung damit, dasselbe Kunststück zu vollbringen? Wenn ja, wie haben Sie herausgefunden, was tatsächlich funktionieren würde, da die dokumentierten Tricks für Maps API v3 nicht funktionieren?
  • Was ist mit dem Laden von Registerkarteninhalten mit Ajax gemäß den jQuery UI-Dokumenten ? Ich hatte keine Chance, damit herumzuspielen, aber ich vermute, dass es Maps noch mehr kaputt machen wird. Wie hoch sind die Chancen, dass es funktioniert (oder lohnt es sich nicht, es zu versuchen)?
  • Wie kann ich dafür sorgen, dass die Karte den größtmöglichen Bereich ausfüllt? Ich möchte, dass es den Tab ausfüllt und sich an die Seitengröße anpasst, ähnlich wie es bei maps.google.com gemacht wird. Aber wie gesagt, ich scheine nicht in der Lage zu sein, nur absolutes CSS für Breite und Höhe auf das Map Div anzuwenden.

Es tut uns leid, wenn dies langwierig war, aber dies ist möglicherweise die einzige Dokumentation für die Registerkarten "Maps API v3 + jQuery". Prost!

Matt Ball
quelle
Ich fand die Google Maps-Gruppe sehr hilfreich bei jquery + maps. Ich habe die Tabs oder JQuery UI jedoch nicht verwendet.
Jay
Soweit ich das beurteilen kann, sind alle Probleme ein direktes Ergebnis des Einfügens der Karte in eine Registerkarte der jQuery-Benutzeroberfläche. Obwohl die Leute in der Kartengruppe vielleicht Erfahrung damit haben, schien es nicht der richtige Ort für diese Frage zu sein. Ich könnte am Ende herumfragen.
Matt Ball
Mist. Sie waren sehr hilfreich beim API-Teil, konnten Ihnen aber auf der jquery-Seite nicht helfen.
Jay
LÖSUNG, DIE FUNKTIONIERT !!! :) stackoverflow.com/questions/12641798/…
Sergio Bilello

Antworten:

22

Hinweis: Diese Antwort erhielt eine ungültige Bearbeitung durch einen Drittanbieter, die im Wesentlichen den Inhalt ersetzte, was ein Drittanbieter-Editor nicht tun sollte. Das Ergebnis ist jedoch möglicherweise nützlicher als das Original, sodass beide Versionen nachfolgend aufgeführt sind:


  • Originalversion von Anon aus dem Jahr 2010 nach einer Bearbeitung durch Anon

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

wird von http://code.google.com/p/gmaps-api-issues/issues/detail?id=1448 als v3-Ersatz für checkResize () von v2 vorgeschlagen.

Blech - schlechtes Google, kein Cookie.


  • Das vollständige Umschreibungsformular 2012 von Benutzer Eugeniusz Fizdejko:

Für mich funktioniert beim Hinzufügen eines Markers:

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

google.maps.event.addListener(map, "idle", function(){
    marker.setMap(map);
});
Anon
quelle
Genial. Ich hatte dieses Problem in einer jquery Mobile / Phonegap-App und dieses Update löste das Problem für mich!
Brade
1
Dies führte mich zu meiner Antwort, der obige Link zu code.google.com wurde vor ein paar Tagen mit Bootstrap-Registerkarten aktualisiert und diese Google Maps-Ausgabe $ ('a [data-toggle = "tab"]'). On ('angezeigt .bs.tab ', Funktion (e) {google.maps.event.trigger (map,' resize '); map.setZoom (map.getZoom ());})
NinjaKC
13

Eigentlich meine Antwort oben kratzen. Die jQueryUI-Website hat die Antwort und hier ist sie:

Warum tut...

... mein Schieberegler, Google Map, sIFR usw. nicht funktionieren, wenn er in einem versteckten (inaktiven) Tab platziert wird?

Jede Komponente, für deren Initialisierung eine Dimensionsberechnung erforderlich ist, funktioniert in einer ausgeblendeten Registerkarte nicht, da das Registerkartenfeld selbst über die Anzeige ausgeblendet ist: Keine, sodass Elemente darin keine tatsächliche Breite und Höhe angeben (0 in den meisten Browsern). .

Es gibt eine einfache Problemumgehung. Verwenden Sie die Technik von links, um inaktive Registerkarten auszublenden. Ersetzen Sie beispielsweise in Ihrem Stylesheet die Regel für die Klassenauswahl ".ui-tabs .ui-tabs-hide" durch

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

Bei Google Maps können Sie die Größe der Karte auch ändern, sobald die Registerkarte wie folgt angezeigt wird:

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

resizeMap () ruft checkResize () von Google Maps auf der jeweiligen Karte auf.

jeffkee
quelle
1
Bearbeiten Sie einfach Ihre alte Antwort, bitte. Darüber hinaus habe ich die Tatsache angesprochen, dass die von der jQueryUI-Site vorgeschlagene Off-Left-Technik in diesem Fall nicht funktioniert.
Matt Ball
Ich entschuldige mich - ich wusste nicht, dass ich einen vorhandenen Kommentar bearbeiten kann. Da ich die ganze Zeit auf Blogs bin, habe ich nur die Angewohnheit zu denken: "Wenn ich es einmal ausgespuckt habe, kann ich es nicht mehr zurücknehmen." Ich kann Ihnen nur sagen, dass auf dieser Seite Karten / Straßenansichten perfekt auf der Registerkarte funktionieren: jackying.brixwork.com/showlisting.php/63/… Das Beste, was ich tun kann, ist, Ihnen den Code zu zeigen, vielleicht können Sie Vergleiche anstellen und sehen, was fehlt / anders ist. Mein Streetview hat mehrere Tage lang NICHT funktioniert, bis ich die von mir veröffentlichte Lösung gefunden habe.
Jefferson
Worauf bezieht sich #example? Ist es die Karte oder die ID der Registerkarte? Ist resizeMap () eine V3-Funktion für Map?
Bo-Oz
12

Definieren Sie einfach die CSS-Klasse für versteckte Registerkarten neu:

.ui-tabs .ui-tabs-hide {
    position: absolute !important;
    left: -10000px !important;
    display:block !important;
}
Mitglied
quelle
Gute Lösung, wenn Sie die G-Map nicht generieren - fügen Sie einfach ein Ein ("Klicken") hinzu, um das CSS der Registerkarte div zurückzusetzen.
Q Studio
9

Folgendes können Sie für Google Maps v3 tun:

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
});
Jayarjo
quelle
Ich bin mir nicht sicher, wie das Leerlaufereignis hilfreich sein soll. Selbst wenn es ausgelöst wird, was nützt es, wenn das Rendering immer noch durcheinander ist, bevor der Benutzer entscheidet, zu ziehen und dann inaktiv zu werden? Die Größenänderung ist nützlich im Kontext eines Tab-Show-Ereignisses oder in einem Timeout / Intervall.
Computrius
4

Ich lade die Karten, nachdem die Registerkarte angezeigt wurde.

Das ist hacky, aber es hat bei mir funktioniert. Speichern Sie einfach die URL des Map-Iframes im iframes rel-Attribut wie folgt:

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

Dieses Ereignis setzt das Attribut iframe src auf die URL in rel.

        $("#tabs").tabs({
            show:function(event, ui) {
                var rel = $(ui.panel).find('iframe').attr('rel');
                $(ui.panel).find('iframe').attr('src',rel);
            }
        });
Keyo
quelle
ok, und wie bist du vom iframe zu den lat- und lon pos-koordinaten gekommen?
Tony
4

Dies beantwortet nicht alle Ihre Fragen, aber ich habe es zum Laufen gebracht und bei allen anderen Antworten fehlt eines: Wenn Sie die Karte mit dem Ereignis "Größe ändern" neu zeichnen, verlieren Sie den Ort, an dem die Karte zentriert war. Sie müssen also auch die Mitte der Karte mit setCenter erneut aktualisieren , wenn Ihre Karte auf einer Position zentriert ist.

Außerdem möchten Sie die Karte nicht jedes Mal initialisieren, wenn der Registerkartenwechsel ausgelöst wird, da dies nicht effizient ist und zu zusätzlichen Geocodes führen kann. Zunächst müssen Sie Ihren zentrierten Standort speichern, der statisch lat / long sein kann oder bei Geokodierung etwa so aussieht:

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);
  }
});

Dann

$("#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!      
    }
});

Dabei ist 'mapTab' die ID Ihres mapTab und 'map' der Variablenname für Ihr Kartenobjekt.

paul
quelle
1
Diese Methode zum Auslösen der Kartengrößenänderung funktioniert auch für Twitter-Bootstrap-Tabs, indem sie an das Tab-Klick-Ereignis gebunden wird :) Ihre Lösung ist die beste hier imo
haxxxton
2

Stellen Sie sicher, dass der Code, der Ihre Karte initialisiert, VOR dem Snippet heißt, das Ihre Registerkarten initialisiert.

Das einzige Ärgernis, das ich hatte, war, dass ein Klick auf die Registerkarte "Karte" den Browser dazu brachte, sich auf die Karte zu konzentrieren, und dass er aus dem Standardrahmen ausbrach, den jQuery um den Container der Hauptregisterkarten legt. Ich habe einen Aufruf false false onclick zum Tag der Kartenregisterkarte hinzugefügt, um die erste zu behandeln, und eine einfache Rahmengröße: 0 auf der Hauptregisterkarte div, um die zweite zu behandeln.

Das alles hat bei mir funktioniert.

Viel Glück!

Vaughn
quelle
1

Ich habe in jedem Forum nach der Antwort darauf gesucht ... alle sagten, sie sollen das benutzen

map.checkResize()

Lösung ... nichts schien zu funktionieren ... dann habe ich ... warum nicht die Registerkarte initialisiert, wenn die Registerkarte angezeigt wird, also habe ich diese verwendet

$("#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" ist die ID meines Tabs, auf dem sich meine Google Map v3 befindet.

Hoffe das funktioniert bei dir!

Dave
quelle
Das hat bei mir sehr einfach und elegant funktioniert. Ich habe die anderen Lösungen ausprobiert, aber ich nehme an, da mein Setup anders war als die obigen Beispiele, hat es nicht funktioniert (insbesondere der Aufruf der Größenänderungsmethode). Aber das tat es, danke!
John Contarino
Ich fand, dass dies mit Aktivieren besser funktionierte, nicht mit Anzeigen. Ich bin mir nicht sicher warum, aber die Show schien meinen Tab einzufrieren und es nicht zuzulassen, dass er jemals wieder kollabiert.
Benjamin
1

Hey Leute, dieser Code behebt den Fehler, funktioniert aber im IE nicht. Nach dem Suchen und Suchen stellte ich fest, dass wir die folgende Zeile hinzufügen müssen und alles perfekt funktioniert:

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

Ich hatte auch dieses Problem, ich habe die Karten über AJAX geladen.

Es scheint, dass das Problem mit dem Prozentsatz darin bestand, dass das Panel keine festgelegte Größe hatte (die das geladene Markup enthielt).

Die Verwendung des folgenden Codes beim Erstellen der Registerkarten hat mir sehr geholfen:

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

Du kannst anrufen

map.fitBounds (Grenzen)

das wird die Aktualisierung tun

Juan Arce
quelle
1
Das einzige Problem mit fitBounds () ist, dass die Karte in die Mitte zurückschnappt, wenn Sie Markierungen verwenden und der Benutzer die Karte gezogen hat.
Mike Purcell
0

Sehr irritierendes Problem, aber mit ein bisschen Hackaround ist es behebbar. Der Schlüssel besteht darin, die relativen # Tabs der Position an die äußere Höhe der einzelnen Registerkarten anzupassen, wenn Sie eine neue auswählen. So habe ich es gemacht:

$('#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);
   }
  });

Hier ist das CSS, das ich verwendet habe:

#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}
Tom Gordon
quelle
0

Ich habe dies einfach zum Laufen gebracht, indem ich die API asynchron geladen und dann einfach loadScriptvon dem <a>Tag aus aufgerufen habe, das mit dem entsprechenden Tab des onclickEreignisses verknüpft ist :

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

Ich hatte das gleiche Problem und keine der Antworten funktionierte für mich. Vielleicht wusste ich nicht, wie ich sie in meinem Code verwenden soll, also habe ich dem Registerkartenmenü ein Onclick-Ereignis hinzugefügt, um Google Map zu initialisieren, und es funktioniert. Ich weiß jedoch nicht, ob es eine gute Praxis ist.

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>
arjang27
quelle
0

Eine weitere Lösung für Maps API v3 (exp) und 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);
    }
  }
});
Wernight
quelle
0

Ich habe getan, was Keith sagt, und es funktioniert für mich. In meinem Fall verwende ich jQuery-Wegpunkte für meine Navigation mit Registerkarten, um den folgenden Code besser zu verstehen:

Im Kopf

<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>

Innerhalb meiner Tabs:

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

Dann im DIV

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

Hoffe das hilft jemandem, danke für alles!

yehanny
quelle
0

Ich hatte das gleiche Problem in Semantic UI, das Problem wurde beim Aufrufen der init();Funktion behoben, wenn ein Tab geladen wurde oder Sie ihn auch binden können.

Moxet Khan
quelle