ACFを使ってカスタム投稿に地図を表示 - WordPress
WordPressのカスタム投稿に地図を表示する場合のメモ書きです。
- カスタム投稿タイプ: 店舗情報(shops)
- カスタムフィールド: Map
(2021.02.12)追記しました
マップを表示するスクリプト(googlemap.js - jQuery)をpure JSに書き換えてみました。
カスタム投稿の設定
参考にさせていただいた記事。
【WordPress】プラグインなしでカスタム投稿タイプにカスタムフィールド(テキスト&画像)を追加する方法
register_post_type() - WordPress Developer Resources
functions.phpに記述。
function create_post_type() {
register_post_type(
'shops',
array(
'label' => '店舗情報',
'public' => true,
'has_archive' => true,
'menu_position' => 3,
'supports' => array(
'title',
'editor',
'author',
'thumbnail',
'revisions'
),
'show_in_rest' => true
)
);
}
add_action('init', 'create_post_type');
ACFのセットアップ
Advanced Custom Fieldsプラグインをインストールして有効にします。
フィールドグループを編集
フィールドタイプで Googleマップ
を選択。
投稿タイプで 店舗情報
を選択。
ACF で Google Maps を使うための準備
参考にさせていただいた記事。
WordPress 投稿ページで Google Map を表示する方法
Field Types > Google Map - ACF Documentation
スタイルの設定
style.css
に記述。
.acf-map {
width: 100%;
height: 400px;
}
.acf-map img {
max-width: inherit !important;
}
スクリプトの作成
ACF
にあるテンプレートをそのまま利用します。
js/googlemap.js
に記述。
(function( $ ) {
/**
* initMap
*
* Renders a Google Map onto the selected jQuery element
*
* @date 22/10/19
* @since 5.8.6
*
* @param jQuery $el The jQuery element.
* @return object The map instance.
*/
function initMap( $el ) {
// Find marker elements within map.
var $markers = $el.find('.marker');
// Create gerenic map.
var mapArgs = {
zoom : $el.data('zoom') || 16,
mapTypeId : google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map( $el[0], mapArgs );
// Add markers.
map.markers = [];
$markers.each(function(){
initMarker( $(this), map );
});
// Center map based on markers.
centerMap( map );
// Return map instance.
return map;
}
/**
* initMarker
*
* Creates a marker for the given jQuery element and map.
*
* @date 22/10/19
* @since 5.8.6
*
* @param jQuery $el The jQuery element.
* @param object The map instance.
* @return object The marker instance.
*/
function initMarker( $marker, map ) {
// Get position from marker.
var lat = $marker.data('lat');
var lng = $marker.data('lng');
var latLng = {
lat: parseFloat( lat ),
lng: parseFloat( lng )
};
// Create marker instance.
var marker = new google.maps.Marker({
position : latLng,
map: map
});
// Append to reference for later use.
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 );
});
}
}
/**
* centerMap
*
* Centers the map showing all markers in view.
*
* @date 22/10/19
* @since 5.8.6
*
* @param object The map instance.
* @return void
*/
function centerMap( map ) {
// Create map boundaries from all map markers.
var bounds = new google.maps.LatLngBounds();
map.markers.forEach(function( marker ){
bounds.extend({
lat: marker.position.lat(),
lng: marker.position.lng()
});
});
// Case: Single marker.
if( map.markers.length == 1 ){
map.setCenter( bounds.getCenter() );
// Case: Multiple markers.
} else{
map.fitBounds( bounds );
}
}
// Render maps on page load.
$(document).ready(function(){
$('.acf-map').each(function(){
var map = initMap( $(this) );
});
});
})(jQuery);
Google Maps APIのキーの取得と設定
Get an API Key - Google Maps Platform
上のページの説明にそって、プロジェクトを選択(または作成)して Credentials
ページを開く。
Create credentials > API key
で Keyを生成。
Application restrictions
HTTP referrers (web sites)
Website restrictions
example.com
(地図を設置するドメインを設定)
有効にするAPI
- Maps JavaScript API
- Geocoding API(住所から場所を指定)
- Places API(著名な場所、任意)
スクリプトの読み込み
functions.php
に記述。
function my_api_key() {
return 'MY_API_KEY';
}
function my_acf_google_map_api( $api ) {
$api['key'] = my_api_key();
return $api;
}
add_filter('acf/fields/google_map/api', 'my_acf_google_map_api');
function add_my_scripts() {
wp_enqueue_script(
'googlemap-script',
get_theme_file_uri( '/js/googlemap.js' ),
array( 'jquery' ),
filemtime( get_theme_file_path( '/js/googlemap.js' ) ),
true
);
wp_enqueue_script(
'googlemapsapi',
'//maps.googleapis.com/maps/api/js?key=' . my_api_key(),
array(),
'',
true
);
}
add_action('wp_enqueue_scripts', 'add_my_scripts');
[2020-12-29]
ハンバーガーメニュー(レスポンシブ対応)表示が動かない場合があったので jQuery(core, migrate)
は WordPress
の初期状態をそのまま利用するようにしました。(追記していた下記の部分を削除)
wp_deregister_script( 'jquery' );
wp_enqueue_script(
'jquery',
'//ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js',
array(),
'3.5.1',
true
);
カスタム投稿(店舗情報)を表示するテンプレート
ファイル構成やスタイル指定など適宜読み替えてください。
single.php
を複製してsingle-shops.php
を作成。
template-parts/content.php
を複製してtemplate-parts/content-shops.php
を作成。
template-parts/content-shops.php
(一部)
the_content( /*...*/ );
$map = get_field('map');
if( $map ): ?>
<div class="acf-map" data-zoom="16">
<div class="marker" data-lat="<?php echo esc_attr($map['lat']); ?>" data-lng="<?php echo esc_attr($map['lng']); ?>"></div>
</div>
<?php endif;
複数のマーカーを表示
こちらの記事にサンプルソースが公開されています。
Create Multiple Marker Map from ACF Google Map Location Field from a CPT
ショートコードによる実装 Multiple shortcode [themeprefix_multiple_marker]
もあります。post_type
を合わせればそのまま使えると思います。
マーカーをカスタマイズ
Customizing a Google Map: Custom Markers - Google Maps Platform
この記事を参考にして js/googlemap.js
を編集します。
function initMarker( $marker, map ) {
// Get position from marker.
var lat = $marker.data('lat');
var lng = $marker.data('lng');
var latLng = {
lat: parseFloat( lat ),
lng: parseFloat( lng )
};
const iconBase = "//developers.google.com/maps/documentation/javascript/examples/full/images/";
const icons = {
parking: {
icon: iconBase + "parking_lot_maps.png",
},
library: {
icon: iconBase + "library_maps.png",
},
info: {
icon: iconBase + "info-i_maps.png",
},
};
// Create marker instance.
var marker = new google.maps.Marker({
position : latLng,
icon: icons["parking"].icon,
map: map
});
// Append to reference for later use.
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 );
});
}
}
pure JSに書き換えてみる
js/googlemap.js
function initMap( acfMap ) {
var markers = acfMap.querySelectorAll( '.marker' );
var mapArgs = {
zoom : acfMap.dataset.zoom || 16,
mapTypeId : google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map( acfMap, mapArgs );
// Add markers.
map.markers = [];
markers.forEach( function( mkr, index ){
initMarker( mkr, map );
});
centerMap( map );
return map;
}
function initMarker( mkr, map ) {
var lat = mkr.dataset.lat;
var lng = mkr.dataset.lng;
var latLng = {
lat: parseFloat( lat ),
lng: parseFloat( lng )
};
const iconBase =
"//developers.google.com/maps/documentation/javascript/examples/full/images/";
const icons = {
parking: {
icon: iconBase + "parking_lot_maps.png",
},
library: {
icon: iconBase + "library_maps.png",
},
info: {
icon: iconBase + "info-i_maps.png",
},
};
// Create marker instance.
var marker = new google.maps.Marker({
position : latLng,
icon: icons[ "parking" ].icon,
map: map
});
// Append to reference for later use.
map.markers.push( marker );
// If marker contains HTML, add it to an infoWindow.
if( mkr.innerHTML ){
// Create info window.
var infowindow = new google.maps.InfoWindow({
content: mkr.innerHTML
});
// Show info window when marker is clicked.
google.maps.event.addListener(marker, 'click', function() {
infowindow.open( map, marker );
});
}
}
function centerMap( map ) {
// Create map boundaries from all map markers.
var bounds = new google.maps.LatLngBounds();
map.markers.forEach(function( marker ){
bounds.extend({
lat: marker.position.lat(),
lng: marker.position.lng()
});
});
// Case: Single marker.
if( map.markers.length == 1 ) {
map.setCenter( bounds.getCenter() );
// Case: Multiple markers.
} else {
map.fitBounds( bounds );
}
}
document.addEventListener("DOMContentLoaded", function(event){
var acfMaps = document.querySelectorAll('.acf-map');
acfMaps.forEach( function( acfMap, index ){
var map = initMap( acfMap );
});
});
上記 js/googlemap.js
を wp_enqueue_script()
で読み込む。
wp_enqueue_script(
'googlemap-script',
get_theme_file_uri( '/js/googlemap.js' ),
array(),
filemtime( get_theme_file_path( '/js/googlemap.js' ) ),
true
);
関数リファレンス/wp enqueue script
これで js/googlemap.js
は jQuery
に依存しなくなったので、このスクリプトが依存するスクリプトのハンドルの配列
を空( array(),
)にしました。
参考記事まとめ
- 【WordPress】プラグインなしでカスタム投稿タイプにカスタムフィールド(テキスト&画像)を追加する方法
- register_post_type() - WordPress Developer Resources
- WordPress 投稿ページで Google Map を表示する方法
- Field Types > Google Map - ACF Documentation
- Get an API Key - Google Maps Platform
- Create Multiple Marker Map from ACF Google Map Location Field from a CPT
- Customizing a Google Map: Custom Markers - Google Maps Platform
Discussion