コードの忘備録です。Wordpressを使用する想定です。
もしかすると、このページに辿り着いたかたはプラグインを期待していたかもしれませんが、コードを組む想定です😅
※記事に緯度経度などの情報を記録するためのカスタムフィールドで Advanced Custom Fieldsを使用しました。
Contents
やりたいこと
カテゴリなどの記事一覧ページに地図を設置し、記事毎に地図にピンを落とすことで、記事一覧からも地図からも記事ページ遷移できるようにしたい。イメージとしては飲食店等のレビューブログといったイメージです。投稿ページの代わりに固定ページで同じことをやれば、ほぼ同じロジックで店舗一覧などにも使えると思います。
投稿記事にカスタムフィールドを追加して緯度、経度、住所、評価等必要項目を追加する。
特定のカテゴリーやタグの投稿一覧ページに表示する投稿の中に緯度・経度の記述があれば、一覧の上部に地図を表示して、地図にピンをマッピングする。
地図の下には記事一覧ページを表示して、一覧からも記事へ遷移できるようにする。
WPのセキュリティアップデートの負担を増やしたくないので、できるだけWordpressのテンプレートに手を入れたくないのですが、テンプレートに手を入れざるを得ません。できる限り作業を最小化するために、直接テーマに手を入れたくない。→これは子テーマを作って対応しましょう。
まず仕様を整理する
GoogleMapsを使用する
まず、地図はGoogle Mapsを使用する。GoogleMapsはGoogle Maps Platformという方式に数年前からかわったので、アカウントを取得しAPIキーを取得します。料金体系とかイロイロ書いてるけど、趣味や中小企業が使う分は概ねタダで使えます。
地図をうまいこと表示する
地図を表示する際に気をつけねばならないことがあります。地図のどのへんの位置に、どのくらいの縮尺で表示するのかを投稿の緯度経度から算出する必要があります。
- 当たり前ですが、投稿の位置を示すピンが全て地図の中に収まっていること。
- 投稿のピンがいい感じにバラける縮尺であること
これらの要件を満たすように、地図の位置と縮尺をjavascrptで計算して求めます。
ブログサイトのルールを決める
今回の投稿の中には緯度経度を含む記事と、含まない記事が混在する想定なので、記事一覧に地図を表示するのは特定のカテゴリのみとすることにしました。
実装
処理の流れ
まず、記事一覧ページに下記のような処理を追加することにしました。
- [WP - Plugin] 記事にカスタムフィールドで緯度経度を登録
- [PHP] 表示する記事一覧から緯度経度情報を持っているものを取得し配列に格納
- [javascript] 配列をすべてGoogleMapsにマッピング
- [javascript] タップした時のイベントもGoogleMapsにマッピング
記事にカスタムフィールドで緯度経度を登録
記事にカスタムフィールドを作りますが、こちらのプラグインが超優秀で便利なのでこれを入れましょう。
記事に緯度経度情報等を保持させる方法や目的などは別のページで説明します。
- 緯度 - xf_lat
- 経度 - xf_lng
でカスタムフィールドを作成してください。
WPで記事一覧の中から緯度経度情報を取得し配列に格納
category.phpなどに下記のコードを書き込みます。上の方がいいかもしれません。
<?php // 記事の緯度経度を取得--?>
<?php
if ( have_posts() ) :
echo '<script>';
echo 'var data = new Array();';
while ( have_posts() ) : the_post();
$xf_lat = get_post_meta(get_the_ID(), 'xf_lat', true);
$xf_lng = get_post_meta(get_the_ID(), 'xf_lng', true);
if($xf_lat && $xf_lng) {
echo 'data.push({';
echo 'lat: "'.$xf_lat.'",';
echo 'lng: "'.$xf_lng.'",';
echo 'url: "'.get_permalink(get_the_ID()).'"';
echo '});';
}
endwhile;
echo '</script>';
endif;
?>
<?php // ここまで?>
ここではカスタムフィールドからxf_latとxf_lngを参照して緯度経度情報を取得しています。値が両方とも入っていればjavascriptの配列に放り込みます。
記事一覧の中に緯度経度を含む記事があったら、問答無用で配列に緯度経度を入れる事になります。
配列をすべてGoogleMapsにマッピング
ここからは特定のマップにピンを落としますが、WPの管理画面からコードを入力します。この処理を入れたいカテゴリーの管理ページの「 説明 」のフォームに下記のスクリプトを貼ればOKです。
※ご使用中のテーマによっては、説明がカテゴリーページに反映されない場合があります。その場合は category.php に追記する必要があります。
※ コード内の***の部分にはGoogleMapsPlatformのAPIキーを入れてください。
<div id="gmaps" style="width: 100%; height: 400px;"></div>
<script type="text/javascript" src="//maps.google.com/maps/api/js?key=****"></script><br />
<script type="text/javascript">
<!--
var lat,lng;
var map = new google.maps.Map(
document.getElementById("gmaps"),{
zoom : 10,
center : new google.maps.LatLng(lat, lng),
mapTypeId : google.maps.MapTypeId.ROADMAP
}
);
// マーカーを生成
var marker = new Array();
for(var i=0; i<data.length; i++){
var lat = data[i].lat;
var lng = data[i].lng;
var url = data[i].url;
marker[i] = new google.maps.Marker({
position: new google.maps.LatLng(lat, lng),
map: map
});
//クリックしたら指定したurlに遷移するイベント
if(url){
google.maps.event.addListener(marker[i], "click", (function(url){
return function(){ location.href = url; };
})(data[i].url));
}
}
// 範囲内に収める
var minX = marker[0].getPosition().lng();
var minY = marker[0].getPosition().lat();
var maxX = marker[0].getPosition().lng();;
var maxY = marker[0].getPosition().lat();;
for(var i=0; i<data.length; i++){
var lt = marker[i].getPosition().lat();
var lg = marker[i].getPosition().lng();
if (lg <= minX){ minX = lg; } if (lg > maxX){ maxX = lg; }
if (lt <= minY){ minY = lt; } if (lt > maxY){ maxY = lt; }
}
var sw = new google.maps.LatLng(maxY, minX);
var ne = new google.maps.LatLng(minY, maxX);
var bounds = new google.maps.LatLngBounds(sw, ne);
map.fitBounds(bounds);
//-->
</script>
まとめ
メモなのでザックリと乱暴な感じですが😅わかりにくいところとかコメントいただければ記事をアップデートします。