Créer une carte google map avec ACF (wordpress)

Créer une carte google map avec ACF (wordpress)

Aujourd’hui nous allons voir comment créer une carte Google Map à l’aide du plugin ACF, version gratuite (version 4  à ce jour).

Si l’on veut une carte avec de multiples marqueurs, chacun renvoyant vers un article ou un custom post type, il existe une foule de tutoriels sur l’utilisation d’ACF en version payante, avec les « repeater fieds » qui facilitent la tache.

Je vous renvoie à ces articles très bien fait.

  • Ashley Cameron (web designer et developpeuse de génie)
  • wp beaches (avec genesis et la version payante d’acf)
  •  et l’excellent tuto de ogrspring (celui ci utilise la version gratuite mais un peu complexe à suivre)

Ici on va voir justement comment parvenir au même résultat avec la version gratuite.

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.

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

(function($) {

/*
* new_map
*
* This function will render a Google Map onto the selected jQuery element
*
* @type function
* @date 8/11/2013
* @since 4.3.0
*
* @param $el (jQuery element)
* @return n/a
*/

function new_map( $el ) {

// var
var $markers = $el.find('.marker');


// vars
var args = {
zoom : 16,
center : new google.maps.LatLng(0, 0),
mapTypeId : google.maps.MapTypeId.ROADMAP
};


// create map
var map = new google.maps.Map( $el[0], args);


// add a markers reference
map.markers = [];


// add markers
$markers.each(function(){

add_marker( $(this), map );

});


// center map
center_map( map );


// return
return map;

}

/*
* add_marker
*
* This function will add a marker to the selected Google Map
*
* @type function
* @date 8/11/2013
* @since 4.3.0
*
* @param $marker (jQuery element)
* @param map (Google Map object)
* @return n/a
*/

function add_marker( $marker, map ) {

// var
var latlng = new google.maps.LatLng( $marker.attr('data-lat'), $marker.attr('data-lng') );

// create marker
var marker = new google.maps.Marker({
position : latlng,
map : map
});

// add to array
map.markers.push( marker );

// if marker contains HTML, add it to an infoWindow
if( $marker.html() )
{
// 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 );

});
}

}

/*
* center_map
*
* This function will center the map, showing all markers attached to this map
*
* @type function
* @date 8/11/2013
* @since 4.3.0
*
* @param map (Google Map object)
* @return n/a
*/

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
map.setCenter( bounds.getCenter() );
map.setZoom( 16 );
}
else
{
// fit to bounds
map.fitBounds( bounds );
}

}

/*
* document ready
*
* This function will render each map when the document is ready (page has loaded)
*
* @type function
* @date 8/11/2013
* @since 5.0.0
*
* @param n/a
* @return n/a
*/
// global var
var map = null;

$(document).ready(function(){

$('.acf-map').each(function(){

// create map
map = new_map( $(this) );

});

});

})(jQuery);

Ces deux bouts de code sont ceux proposés par défaut dans la documentation d’ACF, il ne s »agit là que de simples copier-coller, le code est commenté pour mieux comprendre à quoi sert chaque fonction.

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 );

Maintenant, dans chaque page d’édition d’article, je retrouve une nouvelle meta box avec ma carte google map.

map-in-post

ACF est tellement bien fait qu’il suffit juste de cliquer sur un endroit de la carte, ou d’insérer une adresse, pour que le marqueur se positionne et renvoie une adresse dans le champ. A l’enregistrement de l’article, la carte garde le marqueur en mémoire.

Afficher sa carte sur une page single

Pour afficher la carte de chaque article, on place le code suivant, soit dans single.php, content.php ou tout autre fichier qui renvoie à l’article seul, tout dépend de la manière dont est codé votre thème.

Ici je le place dans single.php, dans la boucle

<?php
while ( have_posts() ) : the_post();

get_template_part( 'template-parts/content', get_post_format() );



$location = get_field('google_maps');

if( !empty($location) ):
?>
<div class="acf-map">
<div class="marker" data-lat="<?php echo $location['lat']; ?>" data-lng="<?php echo $location['lng']; ?>"></div>
</div>
<?php endif; ?>

Je n’ai pas mis ici la fin de la boucle avec le endwhile, mais il faut bien sur penser à le mettre.

Afficher une carte avec les marqueurs de chaque article

Pour l’occasion, plutôt que de créer une page dédiée, je place le code dans mon fichier home.php (page d’accueil), ou je vais afficher la carte avec tous mes marqueurs.(bien sur au préalable je crée mes articles en leur attribuant une longitude et latitude grâce à notre custom field d’ACF) Je crée une section, et je place une nouvelle boucle à l’intérieur.

<section class="no-padding" id="imgHome">
<?php
$articles = get_posts( array(
'post_type' => 'post',
'posts_per_page' => -1
));

if( !empty($articles) ): ?>


<div class="acf-map">

<?php foreach($articles as $article): ?>
<?php
$location = get_field('google_maps',$article->ID);

if( !empty($location) ): ?>

<div class="marker" data-lat="<?php echo $location['lat']; ?>" data-lng="<?php echo $location['lng']; ?>"></div>

<?php endif; ?>
<?php endforeach; ?>

</div>

<?php endif; ?>

</section>

Voila, je retrouve en page d’accueil  ma carte avec mes marqueurs affichés.

Afficher les images à la une

code acf multiple

Une autre approche, avec cette fois l’utilisation une loop classique et l’ajout du titre, du thumbnail, et du lien renvoyant vers l’article.

$args = array(
'post_type' => 'post',
'posts_per_page' => -1,
);
$the_query = new WP_Query($args);
;?>
<div class='acf-map'><?php
while ( $the_query->have_posts() ) : $the_query->the_post();
$location = get_field('google_maps');

if( !empty($location) ) {
?>
<div class="marker" data-lat="<?php echo $location['lat']; ?>" data-lng="<?php echo $location['lng']; ?>">
<?php the_post_thumbnail('thumbnail');?>
<h4><a href="<?php the_permalink(); ?>" rel="bookmark"> <?php the_title(); ?></a></h4>
<p class="address"><?php echo $location['address']; ?></p>
</div>
<?php
}
endwhile;
echo '</div>';
wp_reset_postdata();


;?>

A l’insertion d’un nouvel article, la carte se positionnera de telle sorte que le dernier élément soit visible .

map-accueil

Le CSS

Petit bout de code css pour optimiser l’affichage de la carte :

.acf-map {
width: 100%;
height: 400px;
border: #ccc solid 1px;
margin: 0px auto;
}

Nous verrons dans un prochain article comment on peut améliorer tout cas pour afficher des encarts (titre, texte, photo) au clic sur les marqueurs.

Pour ceux qui n’utilisent pas ACF, il existe des plugins faisant tout le travail

Bonus

Comme on peut le voir sur nos cartes, le code js par défaut de la documentation ACF ne mentionne pas comment fermer automatiquement une « infowindow » (infobulle) quand on en ouvre une nouvelle.Elle restent toutes affichées sur la carte tant qu’on n’a pas cliqué sur la croix.

Voici le code js à rajouter dans notre fichier js pour que ca fonctionne correctement.

On modifier la fonction add_marker comme suit


function add_marker( $marker, map ) {

// var
var latlng = new google.maps.LatLng( $marker.attr('data-lat'), $marker.attr('data-lng') );

// create marker
var marker = new google.maps.Marker({
position : latlng,
map : map
});

// add to array
map.markers.push( marker );

// if marker contains HTML, add it to an infoWindow
if( $marker.html() )
{

// 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() {
if (typeof( window.infoopened ) != 'undefined') infoopened.close();
infowindow.open(map,marker);
infoopened = infowindow;

});
}

}