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;
}
}
Code: Alles auswählen
//google map locations
$address=urlencode($strasse . ", " . $plz . " " . $stadt);
$loc = geocoder::getLocation($address);
print_r($loc); //nur zu Testzwecken ausgeben
$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}
LG, und wenn ihr es einsetzt, gebt doch mal kurzes Feedback, das wäre nett
Viktor