Créer une carte Google Map avec ACF (wordpress) : version 2

A la suite du précédent post sur ACF et les cartes google Map, on va dans ce tuto pousser un peu plus loin pour obtenir ce genre de résultat:

acf-google-map

 

Au clic sur l’une des vignettes à droite, une popup s’ouvre sur le marqueur concerné.La liste à droite qui liste tous mes articles ou j’ai renseigné une adresse, a une hauteur fixe et est en mode overflow-y: scroll, ce qui signifie qu’on peut rajouter autant d’articles que souhaité, un curseur permet de faire défiler la liste

Au préalable, je vous invite à suivre le premier tuto sur le sujet , vous aurez ainsi les bases.
Je retrancris néanmoins tout le code ici

En complément, voici les sources sur lesquelles je me suis largement appuyé pour parvenir à ce résultat

La différence majeure, est que je ne crée pas ici de custom post type, j’utilise un seul champ additionnel, et j’utilise la version gratuite d’ACF.La carte finale est placée sur ma page d’accueil et non une page de custom posts.

Télécharger ACF

Première étape bien sûr, il faut télécharger ACF.

Créer une clé API

Pour faire fonctionner google map dans ACF, il faut une clé API.La procédure peut faire peur au début, mais il suffit de suivre les étapes indiquées ici

Démarrer avec ACF

une fois le tout effectué, on peut aller dans les paramètres du plugin et créer nos custom fields.

Ici on va créer un simple champ additionnel que l’on va nommer google maps.Dans le backoffice, on clique sur l’onglet “ACF“, puis dans “groupe de champs“, on clique sur “ajouter“.

On donne au Titre du champ le nom de Google Maps, le Nom de champ se remplit tout seul, puis on selectionne google map en Type de champ.Le reste on n’y touche pas

acf-google-map

Au bas de la page on définit l’emplacement de ce nouveau champ additionnel.Pour mon exemple, je vais partir sur les articles normaux.

assigner-acf

La documentation ACF

Maintenant dans le code, pour que tout cela fonctionne il faut insérer certaines fonctions, selon les recommandations d’ACF.

Dans functions.php, insérer le code suivant



function my_acf_google_map_api( $api ){
	$api['key'] = 'VotreCléAPI';
	return $api;
}

add_filter('acf/fields/google_map/api', 'my_acf_google_map_api');

Ce code est nécessaire pour que la carte s’affiche.

( A partir de là, le code change par rapport au premier tuto: )

On crée ensuite un fichier js, qu’on nomme par exemple, google.js.A l’intérieur on insère le code suivant:

Dans le fichier js, on va insérer les fonction suivantes :

(function($) {
 
function render_map( $el ) {
    
    // var
    var $markers = $(document).find('.marker');
   
    // vars
    var args = {
        zoom        : 16,
        center      : new google.maps.LatLng(0, 0),
        mapTypeId   : google.maps.MapTypeId.ROADMAP,
        scrollwheel: false,
        mapTypeControlOptions: {
          mapTypeIds: [google.maps.MapTypeId.ROADMAP]
        }
    };
 
    // create map               
    var map = new google.maps.Map( $el[0], args);
 
    // add a markers reference
    map.markers = [];
    // add markers
    index=0;
    $markers.each(function(){
        add_marker( $(this), map, index);
        index++;
    });
   
    // center map
    center_map( map );
 
    }
    
function add_marker( $marker, map, index ) {
 
    // var
    var latlng = new google.maps.LatLng( $marker.attr('data-lat'), $marker.attr('data-lng') );
    var image = new google.maps.MarkerImage("http://localhost/virtual_v2/wp-content/themes/virtualtrip2017/img/map-marker.png", null, null, null, new google.maps.Size(25,30));
 
    // create marker
    var marker = new google.maps.Marker({
        position    : latlng,
        map         : map,
        icon        : image
    });
 
    // add to array
    map.markers.push( marker );
    
    
    // if marker contains HTML, add it to an infoWindow
    if( $marker.html() )
    {
        $('#listdata').append('<div class= "linkage" id="p'+index+'">'+$marker.html()+'</div>'); // change html here if you want but eave id intact!!
         
        $(document).on('click', '#p'+index, function(){
            infowindow.open(map, marker);
            setTimeout(function () { infowindow.close(); }, 3000);
        });
      
        // create info window
        var infowindow = new google.maps.InfoWindow({
            content     : $marker.html(),
        });   
 
        // show info window when marker is clicked
        google.maps.event.addListener(marker, 'click', function() {
 
            infowindow.open( map, marker );
 
        });
 
    }
 
}
 
function center_map( map ) {
 
    // vars
    var bounds = new google.maps.LatLngBounds();
 
    // loop through all markers and create bounds
    $.each( map.markers, function( i, marker ){
 
        var latlng = new google.maps.LatLng( marker.position.lat(), marker.position.lng() );
 
        bounds.extend( latlng );
 
    });
 
    // only 1 marker?
    if( map.markers.length == 1 )
    {
        // set center of map
        alert(bounds);
        map.setCenter( bounds.getCenter() );
        map.setZoom( 16 );
    }
    else
    {
        // fit to bounds
        map.fitBounds( bounds );
    }
 
}
 
// Call it
 
 
  $(document).ready(function(){
 
    $('.acf-map').each(function(){
 
        render_map( $(this) );
 
    });
 
});
 
 
})(jQuery);

On voit ici notamment par rapport à la documentation ACF, la modification de la fonction add_marker : on va voir plus bas l’explication du code

L’appel aux scripts

Il faut ensuite relier tout ca, en allant chercher les scripts de google et notre fichier js

Dans functions.php, à l’intérieur de votre fonction d’appel aux scripts, placez le code suivant

wp_enqueue_script( 'google-map', 'https://maps.googleapis.com/maps/api/js?key=votreCléApi', array(), '3', true );
			wp_enqueue_script( 'google', get_template_directory_uri() . '/js/google.js', array('google-map', 'jquery'), '0.1', true );
	

Comme on le voit dans le premier tuto, on a desormais un champ additionnel dans chaque page d’édition d’article, avec la carte google map;On crée donc plusieurs articles et on renseigne une adresse pour chaque article.

Afficher la carte sur une page dédiée

Maintenant, j’affiche la carte et tous les marqueurs avec le code suivant.Plutot que d’utiliser une boucle, comme dans le tuto cité en exemple, j’utilise le même foreach que dans le premier tuto:   pour mon exemple, je place ce code dans le fichier home.php, mais on peut le mettre ailleurs

<?php 
$post_objects = get_posts( array(
   'post_type' => 'post', 
   'posts_per_page' => -1
));

if( !empty($post_objects) ): ?>
    <?php
    	echo '<div class="locations"><div class="acf-map"></div>';
		echo '<div id="listdata"></div><div id="newdiv">';
   foreach($post_objects as $post){
     setup_postdata($post);

     $location = get_field('google_maps');
     	if( !empty($location) ): 
		printf( '<div class="marker" data-lat="%s" data-lng="%s">
					<h4 class="title">%s</h4>
					<div class="address"><i class="fa fa-map-marker" aria-hidden="true"></i> %s
						<a href="" target="_blank" class="website" title="%s"></a>
					</div>
				</div>',
			     $location['lat'],
			     $location['lng'],
			     get_the_title(),
			     $location['address'],
			     get_the_title());

   
     endif; 
 }
     echo '</div></div>';
    
/* Restore original Post Data */
		wp_reset_postdata();?>
<?php endif; ?>

L’explication du code

Au niveau de la structure de notre bloc, on a à l’intérieur d’une div englobante .locations, d’un coté la carte, avec la div .acf-map, de l’autre coté, la liste avec la div #listdata.Comme on le voit les deux div sont vides.

A la suite, il crée le bloc des marqueurs dans un printf, afin de pouvoir récupérer tout ce code dans le fichier google.js précédemment crée.C’est le js qui avec toutes les données necessaires va créer la carte dans la div acf-map, grace à la dernière fonction du fichier js

$('.acf-map').each(function(){
 
        render_map( $(this) );
 
    });
 

et au niveau de la fonction add_marker()

$('#listdata').append('<div class= "linkage" id="p'+index+'">'+$marker.html()+'</div>'); 

Il injecte avec .append() tout le code html du printf dans une nouvelle div .linkage, dont il incrémente l’ID.

Dans la fonction suivante

$(document).on('click', '#p'+index, function(){
            infowindow.open(map, marker);
            setTimeout(function () { infowindow.close(); }, 3000);
        });

au clic sur chaque div.linkage ciblée par son nouvel ID, il ouvre la fenetre (ou le marqueur) correspondante sur la carte.

En fait, le code dans chaque bloc de notre liste, est l’identique réplique de ce qu’on a dans chaque infowindow(le code dans le printf).

Cette manière de faire peut ne pas convenir dans le sens ou il est difficile ensuite d’afficher les éléments différement : on pourrait par exemple n’afficher dans la liste que des titres, et dans l’infowindow une image, un titre, un extrait..Or la on a deux fois la même chose .

Afficher les thumbnails sur les vignettes

acf-image

On continue néanmoins sur cette version, et pour un visuel plus sympa, on peut rajouter les images à la une des articles sur la colonne des droite et donc aussi à l’intérieur des ‘infowindow’ (les petites fenêtres qui apparaissent au clic)

voici le code à modifier. Dans le fichier home.php

<?php 
$post_objects = get_posts( array(
   'post_type' => 'post', 
   'posts_per_page' => -1
));

if( !empty($post_objects) ): ?>
    <?php
    	echo '<div class="locations"><div class="acf-map"></div>';
		echo '<div id="listdata"></div><div id="newdiv">';
   foreach($post_objects as $post){
     setup_postdata($post);

     $location = get_field('google_maps');


     	if( !empty($location) ): ?>
   
   <?php
		printf( '<div class="marker" data-lat="%s" data-lng="%s">
					<div class="location-image"> '. get_the_post_thumbnail( $post_id, "thumbnail" ) .'</div>
					<div class="text">
					<h4 class="title">%s</h4>
					<div class="address"><i class="fa fa-map-marker" aria-hidden="true"></i> %s
						<a href="" target="_blank" class="website" title="%s"></a>
					</div></div>
				</div>',
			     $location['lat'],
			     $location['lng'],
			     get_the_title(),

			     $location['address'],
			     get_the_title());

   
     endif; 
 }
     echo '</div></div>';
    
/* Restore original Post Data */
		wp_reset_postdata();?>
<?php endif; ?>

Je rajoute donc simplement le code <div class=”location-image”> ‘. get_the_post_thumbnail( $post_id, “thumbnail” ) .'</div> dans a fonction printf, qui est ainsi repris automatiquement dans l’infowindow grace au js.

 

Voici le code css entièrement pris sur le site alansari.io,  légèrement modifié :

/* fixes potential theme css conflict */
.acf-map img {
   max-width: inherit !important;
}
 
.locations {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-flow: row wrap;
        flex-flow: row wrap;
    -webkit-box-pack: justify;
        -ms-flex-pack: justify;
        justify-content: space-between;
}
 
.locations *:nth-of-type(1) {
    -ms-flex-preferred-size: 69%;
        flex-basis: 69%;
}
 
.locations *:nth-of-type(2) {
    -ms-flex-preferred-size: 29%;
        flex-basis: 29%;
}
 
#newdiv {
    display: none;
}
 
#listdata {
    overflow-y: scroll;
    overflow-x:hidden;
    height: 600px;
}
 
.linkage {
    cursor: pointer;
    border-bottom: 1px solid #ddd;
    padding: 30px 30px 30px 30px;
}
 
.linkage:nth-last-of-type(1) {
	border: none;
}
 
.fa-map-marker {
    color: #000;
}

 .acf-map .location-image {
    width:150px;
    height:auto;
    
  
}

.marker{
	display:table;
}

#listdata .location-image, 
#listdata .text{
	display:table-cell;
	padding:10px;
	vertical-align:top;
	width:50%;
}
.acf-map .location-image, 
.acf-map .text{
	display:table-cell;
	padding:10px;
	vertical-align:top;
	}

.text h4{
	margin-top:0;
}

@media only screen and (max-width: 1024px) {
	.locations *:nth-of-type(1),
	.locations *:nth-of-type(2) {
	    -ms-flex-preferred-size: 100%;
	        flex-basis: 100%;
	}
 
	#listdata {
		height: auto;
		overflow: visible;
		display: -webkit-box;
		display: -ms-flexbox;
		display: flex;
		-ms-flex-flow: row wrap;
		    flex-flow: row wrap;
		-webkit-box-pack: justify;
		    -ms-flex-pack: justify;
		        justify-content: space-between;
	}
 
	#listdata * {
		-ms-flex-preferred-size: 49%;
		    flex-basis: 49%;
	}
 
	.linkage {
		margin: 0;
		padding: 40px 40px 0 20px;
	}
 
	.linkage:nth-last-of-type(2) {
		border-bottom: none;
	}
}
 
@media only screen and (max-width: 640px) {
	#listdata * {
		-ms-flex-preferred-size: 100%;
		    flex-basis: 100%;
	}
 
	.linkage:nth-last-of-type(2) {
		border-bottom: 1px dashed;
	}
}

2 thoughts on “Créer une carte Google Map avec ACF (wordpress) : version 2

  1. Fabrice Arnauld

    bonjour,
    super tutoriel… par contre je souhaite aussi modifier les icônes des marker google, suivant plusieurs taxonomy. Chaque category aurait sa propre icon. De plus, éventuellement je souhaite créer un système de filtre. J’ai essayé de mon côté et j’avoue que j’ai du mal à trouver la solution.
    Merci de votre retour éventuel.
    Bien cordialement.

    Reply
    1. copier coller Post author

      Bonjour, merci pour le commentaire!
      pour filter, il y a un exemple par ici
      pour ce qui est des différentes icones, je n’ai pas trouvé d’exemples sur le net..je pense que du coté de stackoverflow il doit y avoir des pistes..n”hésitez pas à revenir et à partager la réponse si vous la trouvez!!
      a bientot

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *