mashup blog. Bringing mashups & web 2.0 down to earth.

 
 Sunday, August 13, 2006

200-300 geografische Punkte mittels Google maps API in eine Map zu laden, ist die Standardaufgabe bei jeder Google Maps integration und stellt keine besondere Herausforderung mehr dar: Sämtliche Punkte bzw. Markers können initial mit addOverlays() geladen werden. Verschiebt der Benutzer den Kartensausschnitt oder Zoomt er aus, sind sämtliche Markers bereits im Hintergrund vorhanden und werden sofort dargestellt. Dies funktioniert soweit gut und stabil für eine fixe und kleine Anzahl Markers, wie z.B. bei dieser Verkehrsunfall-Map.

 

Was aber, wenn nun die Anzahl Marker grösser ist, z.B. für den Fall dass man sämtliche Ortschaften der Schweiz mit einem Marker versehen möchte oder Artikel von eBay oder ricardo auf einer Map positionieren möchte. Hierfür können die Marker nicht mehr alle auf einmal initial geladen werden – die Ladezeit wäre einerseits zu lange, anderseits funktioniert Google Map ab 400-500 geladenen Markers derart langsam (Maus blockiert bis hin zu Browerabsturz), dass es kaum mehr usable ist. Die Lösung hierfür heisst dynamisches Laden der Markers entsprechend dem angezeigten Kartenausschnitt. Ist für die Marker-Daten eine XML-Schnittstelle verfügbar, welche als Parameter die Eckpunkte des angezeigten Kartenausschnitts entgegennimmt, ist auch dies relativ einfach zu realisieren. Das AJAX-konforme Laden der Marker funktioniert dann durch Übergabe eines URL-Strings an das Google Maps Objekt GDownloadUrl, z.B:

 

strFeedUrl = http://www.mydomain.com/api.xml?sw= “ + map.getBounds().getSouthWest() + “&ne= + map.getBounds().getNorthEast();

 

Soweit so einfach – und wahrscheinlich auch schon in zig Google maps so gelöst. Die grössere Herausforderung kommt aber noch: Das Nachladen von Markers sobald der Benutzer den Kartenausschnitt verschiebt oder auszoomt. Da vorhin ja nur die Markers innerhalb des Kartenausschnitts geladen wurden, sind beim Verschieben Teile des neuen Kartenausschnitts noch Marker-los. Um diese wiederum dynamisch nachzuladen, haben wir uns folgende Ansätze angeschaut:

 

1. Überschreiben:  Das einfachste ist, die Markers einfach innerhalb des neuen Kartenausschnitts mit addOverlays() dazuzufügen. Falls der Kartenausschnitt bereits Markers enthielt (vom vorhergehenden Ausschnitt), werden von Google Maps an den identischen Stellen zusätzlicher Marker über die bestelhenden positioniert. Visuell stellen diese übereinander gelegten Markers kein Problem dar und erscheinen als ein Marker (ausser dass der Schatten immer dunkler wird…). Jedoch summiert sich die Anzahl der Markers so sehr schnell, dass die Karte wieder nach einigen Verschiebungen kaum benutzbar wird (z.B. bei 50 Markers auf einem Ausschnitt sind nach 10 Verschiebungen effektiv schon ca. 500 der Map hinzugefügt).

2. Verzögertes Laden:  O’Reilly schlägt in Google Maps Hacks (übrigens empfehlenswert) bei grösseren Mengen Markers vor, diese nicht umgehend beim Verschieben nachzuladen, sondern das Laden der Markers zeitverzögert zur letzten Kartenverschiebung zu laden (z.B. 2 Sekunden mittels setTimeout() verzögert). Dies ist sehr hilfreich, wenn der Benutzer mehrfach hintereinander kleine Verschiebungen des Ausschnitts macht, löst aber das Grundproblem der sich addierenden Anzahl Markers eigentlich nicht.

3. Löschen und neu Laden: Die bei Google Maps Implementationen meist gesehene Lösung ist, nach jedem Verschieben und Zoomen sämtliche Markers mit clearOverlays() zu löschen und jene des aktuellen Kartenausschnitts neu zu zeichnen. Dies funktioniert zwar stabil (z.B. auf Smagoo), ist aber aus folgenden Gründen suboptimal: a) Bereits geladene Markers zeigen ein kurzes Flackern, da sie zuerst entfernt und dann wieder angezeigt werden. b) Das Datenvolumen, welches im Hintergrund transferiert wird, ist grösser (da immer wieder sämtliche Punkte des Ausschnitts geladen werden) – für den Benutzer tritt eine spürbare Ladeverzögerung auf. c) Verschiebt der Benutzer einen Ausschnitt wieder zurück auf einen Bereich, der bereits vorhin geladen war, sind die ursprünglichen Markers weg und werden nur zeitverzögert wieder nachgeladen.

4. Markers mit ID: Wenn jeder Marker mit einer ID versehen wird, kann beim Nachladen von Markers überprüft werden, ob dieser auf der map noch fehlt – und nur dann der Map hinzugefügt werden. Dies dürfte einfach funktionieren, wenn die IDs ein drei- oder maximal vierstelliger Integerwert sind, so dass z.B. direkt mit arrLoaded[intId] == true ? überprüft oder gesetzt werden kann, ob der Marker geladen ist. Ist keine solche ID vorhanden (wie z.B. bei velyoo für eBay-Arikeln, wo die ID eine zwölfstellige Zahl ist) muss die performance-aufwändiger durch loopen des Arrays gelöst werden, was ebenfalls bei grösseren Markerzahlen unpraktikabel wird: Um in einem Loop 500 geladene Artikel mit 100 neuen zu vergleichen sind bis zu 50'000 Iterationen notwendig.

5. Nachladen des Kartenausschnitt-Deltas: Für velyoo haben wir schlussendlich diese – aus meiner Sicht optimale Variante – entwickelt. Dabei wird beim Verschieben der Karte die Differenz der beiden Flächen vor dem Verschieben und nach dem Verschieben (oder Zoomen) ermittelt. Die Fläche ist in folgender Grafik gelb dargestellt:

map1.GIF 

Dieses Delta lässt sich wiederum in drei Rechtecke (bzw. bei Zoom vier) unterteilen, welche einfach analog dem gesamten Kartenausschnitt geladen werden können. Eine neue Schwierigkeit tut sich allerdings auf, weil man so die bereits geladenen Kartenausschnitte über mehrere Verschiebungen hinweg speichern muss. Je nach Richtung der Verschiebung können dabei Flächen entstehen, welche die Speicherung der geladenen Markers bzw. Berechnung der zu ladenden Markers sehr schwierig wird. Folgende Illustration soll diese Schwierigkeit aufzeigen (grau = geladene Ausschnitte, weiss = ungeladen, gelb = für aktuellen Ausschnitt nachzuladen):

map2.GIF

Rein programmiertechnisch wär die Speicherung und Berechnung zwar möglich, wesentlich einfache ist allerdings folgende Näherungslösung, welche den Zweck ebenfalls erfüllt: Anstatt das exakte Delta von Kartenausschnitten zu laden, wird das Delta so vergrössert, dass wiederum ein einfach speicherbares Rechteck entsteht. Dadurch werden zwar etwas mehr Bereiche als gerade benötigt in die Karte geladen. Bei einem üblichen Verschiebevorgang, der sich rund um den Initialpunkt bewegt, sind die zusätzlichen Daten jedoch meist geringfügig, die dadurch verursachte Ladeverzögerung vernachlässigbar.

map3.GIF

(grau = geladene Daten, rot = neuer Kartenausschnitt, gelb = zu ladende Daten in der Vereinfachung). Dieser Mechanismus ist bei velyoo z.B. unter im Bike Marktplatz implementiert. Javascript-Funktionen, in welchen obige Erläuterungen umgesetzt sind, finden sich unter http://www.velyoo.com/res/mapHelpers.js.

google | map | mashup
Marco Hassler | # | Comments [3] | Trackback
Related Posts:
Mashups programmieren - oder "the making of velyoo.com"
Relief Karten-Layers für Google Maps
Google Mapplets - Mashup direkt auf Google Maps
Google maps und die dritte Dimension
Differenzierungsmerkmale von Mashups – Beispiel Visual Search
Mashups für Dummies

Tracked by:
http://www.google.com/search?q=tegdblqb [Pingback]
http://nymc.edu/people/indviewg.asp?which=yarqheqa [Pingback]
http://cu-portland.edu/news/detail.cfm?news_id=2995 [Pingback]
http://nymc.edu/people/indviewg.asp?which=wqvxuzge [Pingback]
http://www.valenciacc.edu/leadership/details.cfm?EventID=36449737 [Pingback]
http://support.businessobjects.com/forums/message.asp?mid=171582 [Pingback]
http://www.das.psu.edu/news/fullstory.cfm?newsID=1028 [Pingback]
http://cu-portland.edu/news/detail.cfm?news_id=2993 [Pingback]
http://www.peralta.edu/apps/page.asp?q=Pharmacy (item 35249) [Pingback]
http://www.sanantonio.gov/publicart/news_detail.asp?newsid=143 [Pingback]
http://www.elon.edu/predictions/prediction2.aspx?id=mdmgdmla [Pingback]
http://www.peralta.edu/apps/page.asp?q=Pharmacy (item 55575) [Pingback]
http://www.cvcc.edu/department/news/news.asp?b=474 [Pingback]
http://www.elon.edu/predictions/prediction2.aspx?id=tdxfjcsm [Pingback]
http://www.ion.illinois.edu/askION/answers3.asp?question=219 [Pingback]
http://nymc.edu/people/indviewg.asp?which=nxznvzjk [Pingback]
http://nymc.edu/people/indviewg.asp?which=bbtftrze [Pingback]
http://law.usc.edu/news/article.cfm?newsID=880 [Pingback]
http://www.ion.illinois.edu/askION/answers3.asp?question=234 [Pingback]
http://law.usc.edu/news/article.cfm?newsID=875 [Pingback]
http://www.elon.edu/predictions/prediction2.aspx?id=yqqbipyl [Pingback]
http://aces.uiuc.edu/Calendar/calendar_event.cfm?EventID=1082 [Pingback]
http://cu-portland.edu/news/detail.cfm?news_id=2999 [Pingback]
http://law.usc.edu/news/article.cfm?newsID=858 [Pingback]
http://www.peralta.edu/apps/page.asp?q=Pharmacy (item 17995) [Pingback]
http://law.usc.edu/news/article.cfm?newsID=866 [Pingback]
http://www.elon.edu/predictions/prediction2.aspx?id=ikburpnz [Pingback]
http://www.elon.edu/predictions/prediction2.aspx?id=tzqekuir [Pingback]
http://www.peralta.edu/apps/page.asp?q=Pharmacy (item 74709) [Pingback]
http://law.usc.edu/news/article.cfm?newsID=878 [Pingback]
http://www.peralta.edu/apps/page.asp?q=Pharmacy (item 88016) [Pingback]
http://cu-portland.edu/news/detail.cfm?news_id=3006 [Pingback]
http://www.gse.buffalo.edu/news/viewnews.asp?id=206 [Pingback]
http://e01c.net/_1ja [Pingback]
http://e01c.net/_1cc [Pingback]
http://e01c.net/_15e [Pingback]
http://e01c.net/_zg [Pingback]
http://e01c.net/_si [Pingback]
http://e01c.net/_lk [Pingback]
http://e01c.net/_em [Pingback]
http://e01c.net/_7o [Pingback]
http://e01c.net/_q [Pingback]
http://e01c.net/_3cn [Pingback]
http://e01c.net/_35p [Pingback]
http://e01c.net/_2zr [Pingback]

8/22/2006 9:47:56 PM UTC
Vielen Dank für den Tip - das ist echt der Hammer!
Phillip
8/27/2006 10:43:11 PM UTC
Ein interessanter Bericht und für die Lösung "Bike Marktplatz" auch sicherlich anwendbar.

Bei uns jedoch (http://www.smagoo.ch) ist die Lösung nach dem Punkt 5 überhaupt keine alternative, noch eine korrekte.
Warum? Ganz einfach, Lösung Nummer 5 würde bei uns Resultate liefern, die nicht auf der der Karte sichtbar sind. Ich liefere dem User eine Bar und er findet sie auf der Karte nicht, die er sozusagen definiert hat, sondern weiter draussen, ausserhalb seines gewählten Bereiches. Vielleicht habe ich deinen 5. Punkt auch missverstanden, aber ich denke, bei diesem Punkt sind auch die Markers und deren Resultate gegeben, die sowohl im gelben als auch im grauen Bereich zu finden sind.

Wir wollen nur die Resultate, die sowohl links mit den Markers, als auch rechts in der Liste übereinstimmend vorhanden und angezeigt werden. www.smagoo.ch lebt von dieser Übereinstimmung, vor allem, wenn der User mehrere Suchen gleichzeitig anschauen möchte, wie zB. er muss über Mittag schnell zu seinem Coiffeur und will schnell sehen, obs ein gutes Restaurant im gleichen Kartenausschnitt gibt und vielleicht braucht er für das ausserordentlich angesetzte Meeting eine neue Hose sucht das auch im gleichen Gebiet, dann dürfen und wollen wir ihm nur die Resultate liefern, die auch in seinem von ihm gewählten Bereich zu finden sind und nicht ausserhalb.

Wir haben sicherlich nicht die perfekte Lösung. Apropos Lösung, unsere Lösung basiert übrigens nicht auf die von dir gemeinten Lösung 3, sondern basiert in den Grundzügen (wir machen noch ein bischen mehr als das) auf der Lösung 4. Du wirst bei uns auch kein flakern der Marker sehen. Das Resultat rechts hingegen, sprich die Liste, die wird jedesmal neu aufgebaut. Hier besteht sicherlich noch optimierungs Bedarf, aber momentan funktioniert dies für uns so am besten, ohne komplexe Text heraus- und hinein-schneiderei betreiben zu müssen.

Aber es macht spass zu sehen, dass sich auch andere Menschen den Kopf über solche Dinge zerbrechen ;-)
Weiter so!

Beste Grüsse,

Rob
Technical & Development Director
smartGuide AG

http:www.smagoo.ch

--

Sie sagen ?Sukiyaki? - Wir sagen Sala of Tokio!
www.smagoo.ch - The smart Guide for good things!

::::::::::::::::::::::::::::::::::::::::::::::::
8/28/2006 3:40:10 PM UTC
Vielen Dank für den interessanten Beitrag.

Ich glaub man muss zwei Sachen auseinander halten: Das eine sind die Markers innerhalb der Karte, das andere die Resultate-Liste auf der Seite nebendran. Die Resultate-Liste auf der Seite - da stimm ich mit dir überein - muss 1:1 mit dem gewählten Kartenausschnitt übereinstimmen, sonst wird der Benutzer verwirrt (die Karten-Benutzung und die dynamische Resultate-Liste sind ja eh schon genügend Herausforderung für den unbedarften Internetnutzer). Von den Markers auf der Karte kann ich aber schon mehr im Hintergrund laden, als effektiv auf der Karte sichtbar sind. Dies hat z.B. den Vorteil, dass wenn der Benutzer den Kartenausschnitt verschiebt, Markers bereits eingezeichnet sind, auch wenn er die Maustaste noch nicht losgelassen hat (sonst erst z.B. beim moveend-event). Ich vermute, dass dies ("Karte mal etwas in alle Richtungen verschieben, um zu schauen, obs in der Nähe sonst noch was gibt") ein relativ häufiger Anwendungsfall ist, deshalb Vorladen meiner Meinung sinnvoll. velyoo lädt deshalb z.B. auch etwas mehr Markers rund um den gezeigten Kartenausschnitt vor, um die schon mal auf der Map zu haben (zusätzlich zum erklärten Rechteck-Mechanismus). Ob das schlussendlich auch bei smagoo eine Lösung für die gestellten Anforderungen ist oder nicht, kannst du sicher besser beurteilen. Ein Post, wie ihrs jetzt gelöst habt, wär natürlich auch interessant - jedenfalls viel Erfolg!
Marco
Name
E-mail
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):

On this page....
Archive

<December 2008>
SunMonTueWedThuFriSat
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

More Information
Categories Blogroll
 RSS 2.0  Atom 1.0

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.


Sign In


© Copyright 2008, Marco Hassler