[Anleitung Smarty] Google Map MarkerClusterer

Alles rund um Module und Plugins in CONTENIDO 4.9.
Antworten
homtata
Beiträge: 1142
Registriert: Mi 14. Jan 2004, 14:41
Kontaktdaten:

[Anleitung Smarty] Google Map MarkerClusterer

Beitrag von homtata » Mo 10. Okt 2016, 21:57

Hallo Gemeinde,

ich musste in den letzten Tagen für ein Projekt eine GoogleMap einbauen, die ihre Daten aus der DB bezieht, Geocoding betreibt UND dann noch das MarkerClustering macht wie hier gezeigt:
https://github.com/googlemaps/js-marker-clusterer

Das Geocoding (= das Umrechnen einer Straßenadresse in Längen-/Breitengrad) betrieb ich anfangs direkt im GoogleMaps-Code, javascript-basiert, sozusagen live über eine eigene API, aber das führte zu Meldungen, dass zu viele Geocodinganfragen abgesetzt wurde (selbst 10 Einträge waren zuviel); der API-Key hat darauf keinen Einfluss. Daher brauchte ich ein PHP-gestütztes Geocoding mit Speicherung in der Datenbank.

Unabhängig von dieser ganzen Geschichte werden beim MarkerClusterer je nach Zoomstufe Marker gruppiert und gezählt. Das wiederum hat auch an verschiedenen Stellen gehakt, daher hier ein kurzer Abriss:

- Beim Speichern der Adressdaten über ein Formular habe ich über einen PHP-Codeschnipsel Längen- und Breitengrad für die Adresse berechnet und in die Datenbank gespeichert.
- Zur Erstellung der Karte zog ich alle nötigen Adressdaten und sonstigen Anzeigewerte (Namen, Staaten, Bilder) ebenfalls aus der Datenbank. Der ganze für Google Maps nötige Datenbestand wanderte in ein Array, das an Smarty übergeben wird.
- Neben der remote aufzurufenden Google Maps-Api bedarf es für das MarkerClustering noch lokaler Dateien, die vom o.g. Link stammen und die ich (Stand 10.10.2016) unten in die Zip-Datei gepackt habe: eine Javascript-Datei sowie diverse Bilder, die genau so nach /cms/ hochzuladen sind, wie in der ZIP angelegt. Beim o.g. Link gibt es alternative Icons für das Clustering, dann muss der Link in Smarty anders enden (jetzt heißt er "markerclusterer/m" -> würden die Bildernamen mit "p" gekennzeichnet sein, hieße der Link "markerclusterer/p"). So sind auch eigene Icons möglich und aufrufbar.
- Ihr benötigt einen eigenen API-Key für Google Maps, der aber leicht generiert werden kann. Das erhöht u.a. Euer Limit auf die Kartenzugriffe pro Tag.

Hier die php-Class, die aus der Straßenadresse die Koordinaten berechnet (Geocoder), Quelle: https://www.codeofaninja.com/2014/06/go ... e-php.html

Code: Alles auswählen

class geocoder{
	static private $url = "http://maps.google.com/maps/api/geocode/json?sensor=false&address=";
	
	static public function getLocation($address){
		$url = self::$url.urlencode($address);
		
		$resp_json = self::curl_file_get_contents($url);
		$resp = json_decode($resp_json, true);
		
		if($resp['status']='OK'){
			return $resp['results'][0]['geometry']['location'];
		}else{
			return false;
		}
	}
	
	
	static private function curl_file_get_contents($URL){
		$c = curl_init();
		curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($c, CURLOPT_URL, $URL);
		$contents = curl_exec($c);
		curl_close($c);
		
		if ($contents) return $contents;
		else return FALSE;
	}
}
Im Modulout lässt sich das über die Straßenadresse wie folgt aufrufen. Die Quellen für die Variablen müsst ihr natürlich selbst vorher belegen, wo immer die auch herkommen:

Code: Alles auswählen

//google map locations
$address=urlencode($strasse . ", " . $plz . " " . $stadt);
$loc = geocoder::getLocation($address);
print_r($loc); //nur zu Testzwecken ausgeben
$loc[lat] beinhaltet dann die Latitude.
$loc[lng] die Longitude.
Liefert $loc == false, dann speichere ich in der DB für beide Werte "0" ab -> im Smarty ist das später eine if-Abfrage, um solche Einträge zu unterdrücken. Manchmal ist über das Geocoding einfach die Adresse nicht zu finden, soll aber auch die Karte nicht zum Absturz bringen.

Baut Euch ein Array $addresslist auf, das alle Daten pro Datensatz enthält. Wie ihr im Smarty-Template seht, habe ich verschiedene Keys definiert pro Datensatz: mapslat, mapslng, street, zip, city, company, thumb und popup (da ich mit Bildern arbeite).

Hier das Smarty-Template für diese Vorgehensweise... "options" bestimmt wie gesagt die Darstellung der Cluster-Icons. "gridSize" bestimmt, wie nah die Punkte beieinander liegen müssten, um in einer bestimmten Zoomstufe zusammengefasst zu werden. Kleinere Nummer: Der Radius für ein Cluster ist klein. Je größer die Nummer, desto früher wird zusammengepackt. Eigenen API-Key im unteren Skriptaufruf nicht vergessen! Einige Werte selbst anpassen, nur Mut. Das Infowindow locations[20] lässt sich aus dem locations-Array schön zusammenpuzzeln und mit CSS stylen.

Smarty Template:

Code: Alles auswählen

<div id="googlemaps">
	<div id="map"></div>
</div>

{literal}

<script type="text/javascript">
	function initMap() {
		var map = new google.maps.Map(document.getElementById('map'), {
			zoom: 2,
			center: {lat: 28.3439907, lng: -74.0598095}
		});
		
        var options = {
			imagePath: 'images/markerclusterer/m',
			gridSize: 30
        };
		
    	var marker, i;		 
		 var markers = new Array();

		for (i = 0; i < locations.length; i++) {
		 
			 locations[i][20] = '<div id="content">' +
				 '<div id="siteNotice">' +
				 '</div>' +
				 '<h1 id="firstHeading" class="firstHeading" style="display: none;">' + locations[i][2] + '</h1>' +
				 '<div id="bodyContent">' + 
				 '<div class="address"><p><b>' + locations[i][3] + '</b><br>' + locations[i][4] + '<br>' + locations[i][5] + ' ' + locations[i][6] + '</p>'+ '</div>' +
				 '<div class="image"><a href="' + locations[i][8] + '" rel="lightbox[gallery]"><img src="' + locations[i][7] + '" ></a></div>' +
				 '</div>' + 
				 '</div>';		 
			 
			 var infowindow = new google.maps.InfoWindow({
				 content: locations[i][20]
			 });		
			 var marker = new google.maps.Marker({
				 map: map,
				position: {lat: locations[i][0], lng: locations[i][1]},
				 title: locations[i][2]
			 });
	
			markers.push(marker);
		 
			google.maps.event.addListener(marker, 'click', (function(marker, i) {
				return function() {
					infowindow.setContent(locations[i][20]);
				  infowindow.open(map, marker);
				}
			  })(marker, i));													 
	}	
        // Add a marker clusterer to manage the markers.
		var markerCluster = new MarkerClusterer(map, markers, options);
	}	
			var locations = [
		
		{/literal}
			
			{foreach from=$addresslist item=address}
		 {if $address.mapslat neq 0 } [{$address.mapslat}, {$address.mapslng}, '{$address.street} {$address.zip} {$address.city}', '{$address.company}', '{$address.street}', '{$address.zip}', '{$address.city}', '{$address.thumb}', '{$address.popup}'], {/if}
			 {/foreach}
													 
		 {literal}
		 ];

</script>
<script src="js/markerclusterer.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=HIEREURENEIGENENAPIKEYEINFUEGEN&signed_in=true&callback=initMap"
async defer></script>
{/literal} 
In den auf den o.g. Seiten gezeigten Beispielen wollte die vorgeschlagene Reihenfolge diverser Variablenaufrufe einfach nicht zum Erfolg führen; ich habe solange umgestellt und verschoben, bis es schlussendlich in dieser Kombination passte...

LG, und wenn ihr es einsetzt, gebt doch mal kurzes Feedback, das wäre nett ;-)

Viktor
Dateianhänge
google_maps_markerclusterer.zip
Bilder und JS-Datei für /cms
(31.08 KiB) 117-mal heruntergeladen
Zuletzt geändert von homtata am Mi 12. Okt 2016, 10:11, insgesamt 1-mal geändert.

Faar
Beiträge: 1915
Registriert: Sa 8. Sep 2007, 16:23
Wohnort: Brandenburg
Kontaktdaten:

Re: [Anleitung Smarty] Google Map MarkerClusterer

Beitrag von Faar » Di 11. Okt 2016, 11:58

Danke! :)

Momentan kann ich es nicht testen aber es klingt sehr interessant.
Fliegt der Bauer übers Dach, ist der Wind weißgott nicht schwach.

rethus
Beiträge: 1851
Registriert: Di 28. Mär 2006, 11:55
Wohnort: Mönchengladbach
Kontaktdaten:

Re: [Anleitung Smarty] Google Map MarkerClusterer

Beitrag von rethus » Mi 12. Okt 2016, 15:01

Benötige es momentan nicht, aber dennoch Danke fürs teilen :!:
Could I help you... you can help me... buy me a coffee . (vielen ❤ Dank an: Seelauer, Peanut, fauxxami )

xstable.com: - HighSpeed Hosting, Domains, DomainReselling, Linux-Administration
suther.de: - App-Programierung, High-Performance-Webpages, MicroServices, API-Anbindungen & Erstellung

Software... ein Blick wert: GoogleCalender Eventlist, xst_dynamic_contentType

Antworten