Custom Maps mit ACF Pro Google Maps

Mousewheel Zoom, Infobox Control & beliebig viele Location Markers mit Custom Icons

Maps Plugins für WordPress gibt es wie Sand am Meer. Aber warum auf eine weiteres Plugin zurück greifen, wenn das Advanced Custom Fields Plugin (ACF) onhnehin zum Einsatz kommt und diese Funktion auch bietet?
Die hier vorgestellte Lösung setzt das ACF Pro Plugin voraus – eine Investition die jedem WordPress Worker ans Herz gelegt sei – um Repeater Fields für mehrere Marker auf einer Karte nutzen zu können.
Die out-of-the-box Optionen für ACF Google Maps sind allerdings eher überschaubar, so dass hier für einen Travel Blog etwas Arbeit nötig war um erweiterte Funktionen zu integrieren:

  • Das Zoom Level kann für jeden Post einzeln festgelegt werden
  • Mousewheel Zoom für jeden Karte an-/abschaltbar, damit bei sehr breiten Maps versehentliches einzoomen (während eigentlich die Seite gescrollt werden soll) verhindert wird
  • Für jeden Marker kann – neben Titel, Bild und Beschreibung – ein individuelles Icon angelegt werden
  • Marker Infoboxen werden beim Laden der Map wahlweise offen oder geschlossen dargestellt

ACF Pro Google Map extended

In der Dokumentation zum ACF Google Maps Field wird gut erläutert wie das grundlegende Setup zu bewerkstelligen ist. Darauf basierend sehen die Anpassungen so aus:


Basic Styling im Theme Stylesheet:

.acf-map { width:100%; height: 450px; }
.acf-map img { max-width: inherit !important; }

Erweiterungen der Theme functions.php

Diese Erweiterungen sind nicht notwendig, aber empfohlen.
In der ersten Funktion wird die Höhe der Map-Vorschau im Backend festgelegt, die ansonsten aus den Map Settings kommen würde. Da es beim Bearbeiten umständlich sein kann, durch eine Marker Liste mit 450 Pixeln hohen Maps zu scrollen, wird ein kleinerer Wert gesetzt.
Die zweite Funktion legt eine zusätzliche Bildgröße an, um die Ladezeiten einer Seite nicht durch große Bilder in der Infobox der Map zu verschlechtern.

/* Überschreibt die für die Vorschau im Backend verwendeten Map Settings, die hier zu hoch sein könnten */
add_action('admin_head', 'acf_maps_size');
function acf_maps_size() { echo '<style>td.acf-field-google-map .canvas { height:125px!important; }</style>'; }

// zusätzliche Bildgröße die für Bilder in den Marker Infoboxen genutzt wird
if ( function_exists( 'add_image_size' ) ) { add_image_size( 'location-gmap-infobox-thumb', 250, 75, true ); /*(cropped)*/ }

Ausgabe im Theme

<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>

<script type="text/javascript">
(function($) {
 function new_map( $el ) {
  var $markers = $el.find('.marker');
  var args = {
   zoom : <?php echo the_field('location_gmap_zoom'); ?>,
   center : new google.maps.LatLng(0, 0),
   <?php if( get_field('location_gmap_mousewheel') ) { echo 'scrollwheel: false,'; } ?>   
   mapTypeId	: google.maps.MapTypeId.ROADMAP
 };
 var map = new google.maps.Map( $el[0], args);
 map.markers = [];
 $markers.each(function(){
 add_marker( $(this), map );
 });
 center_map( map );
 return map;
}
function add_marker( $marker, map ) {
 var latlng = new google.maps.LatLng( $marker.attr('data-lat'), $marker.attr('data-lng') );
 var icon = $marker.attr('data-icon');
 var marker = new google.maps.Marker({
  position : latlng,
  icon : icon,
  map : map
 });
 map.markers.push( marker );
  if( $marker.html() ) {
   var infowindow = new google.maps.InfoWindow({
   content : $marker.html(),
   maxWidth: 250
  });
 google.maps.event.addListener(marker, 'click', function() {
  infowindow.open(map,marker);
 });
 <?php if( get_field('location_gmap_marker_infobox_open') ) { echo 'setTimeout(function() { infowindow.open(map, marker); }, 300);'; } ?>        
 google.maps.event.addListener(marker, 'click', function() {
  infowindow.open( map, marker );
 });			
 }
}
function center_map( map ) {
 var bounds = new google.maps.LatLngBounds();
 $.each( map.markers, function( i, marker ){
  var latlng = new google.maps.LatLng( marker.position.lat(), marker.position.lng() );
  bounds.extend( latlng );
 });
 if( map.markers.length == 1 )
  { map.setCenter( bounds.getCenter() );
    map.setZoom( <?php echo the_field('location_gmap_zoom'); ?> ); }
 else { map.fitBounds( bounds ); }
}
var map = null;
$(document).ready(function(){
 $('.acf-map').each(function(){
 map = new_map( $(this) );
});
});
})(jQuery);
</script> 
<?php if( have_rows('location_gmap_markers') ): ?>
 <div class="acf-map">
  <?php while ( have_rows('location_gmap_markers') ) : the_row(); $location = get_sub_field('location_gmap_marker_location'); ?>
   <div class="marker" data-lat="<?php echo $location['lat']; ?>" data-lng="<?php echo $location['lng']; ?>" data-icon="<?php if( get_sub_field('location_gmap_marker_icon') ): echo the_sub_field('location_gmap_marker_icon'); ?><?php endif; ?>">
	<h4><?php the_sub_field('location_gmap_marker_title'); ?></h4>
	<?php $image = get_sub_field('location_gmap_marker_img'); $size = 'location-gmap-infobox-thumb';  
	if( $image ) { echo wp_get_attachment_image( $image, $size ); } ?>
	<p class="address"><?php echo $location['address']; ?></p>
	<?php the_sub_field('location_gmap_marker_description'); ?>
   </div>
  <?php endwhile; ?>
 </div>
<?php endif; ?>

ACF Fields anlegen

Die benötigten Map Fields können hier zum Import herunter geladen werden (entpacken und unter Eigene Felder -> Werkzeuge importieren):

Damit kann jetzt für jeden Post eine Google Map mit einem oder mehreren Markern erstellt werden:

ACF Pro Google Map extended Admin Fields


Custom Marker Icons

Eine umfangreiche Sammlung an Map Icons findet sich z. B. bei der mapicons collection. Die Icons werden über den WordPress Media Uploader eingebunden, dabei empfiehlt sich die Verwendung eines Media Taxonomy Plugins, um jederzeit die Icons filtern zu können.

ACF Pro Google Map extended Custom Marker Icons