個人サイトで登山のルート写真を連携させて表示させています。
スマホで登山時に軌跡をGPXファイルとして保存しておき、あとから写真のexifファイルにGPS座標を挿入します。
ブログにその写真をアップして、同時にGPXファイルをアップするとGoogleMapに軌跡と写真を撮影したポイントが表示される仕組みです。
上記のような感じで写真にタイトルをつけてプロットするのです。
さらに写真をクリックすると地図情報、撮影情報が表示される仕組みです。
登山、サイクリング、ツーリング、ハイキング、旅ジョギングなどを趣味としている人にとっては欲しい機能ではないでしょうか。今まで自前のCMSで行っていましたが、これをWordPressの既存プラグインと独自プラグインの組み合わせで実現できるか模索してみます。
基本的な仕組み
- 写真をアップロードする際に画像ファイルのexif情報を読み出して投稿タイプのメディアのカスタムフィールドに緯度と経度を保存する。
- 登山記録用のページに各種情報を追加できるようカスタムフィールドを設定する
- 軌跡情報であるGPXファイルをページに添付する
- 写真を登山記録用のページと関連付ける
- ページ内にルートと写真タイトルと座標がプロットされた地図を表示する
- サムネイルや地図がプロットされたら写真ページに移動して詳細地図を表示する
写真をアップロードする際に画像ファイルのexif情報を読み出して投稿タイプのメディアのカスタムフィールドに緯度と経度を保存する
こちらは既存のプラグインで対応できるかと思ったのですが、緯度、経度といった値を直接カスタムフィールドに入れてくれるプラグインは見つかりませんでした。自作するしかなさそうです。アップロード時に動作する必要があるので、add_attachment で呼び出しですね。
<?php
// メディアアップロード時に呼び出されるフックを設定
add_action('add_attachment', 'exif_gps_data_on_upload');
// メディアアップロード時の処理
function exif_gps_data_on_upload($attachment_id) {
// 画像のメタデータを取得
$meta = wp_get_attachment_metadata($attachment_id);
// Exifデータがあるか確認
if (isset($meta['image_meta']['camera'])) {
// GPS情報があるか確認
if (isset($meta['image_meta']['latitude']) && isset($meta['image_meta']['longitude'])) {
// GPS情報を取得
$latitude = $meta['image_meta']['latitude'];
$longitude = $meta['image_meta']['longitude'];
// カスタムフィールドに緯度と経度を保存
update_post_meta($attachment_id, 'latitude', $latitude);
update_post_meta($attachment_id, 'longitude', $longitude);
}
}
}
?>
これでGPSデータはカスタムフィールドに保存されます。
登山記録用のページに各種情報を追加できるようカスタムフィールドを設定する
次はページに入れるカスタムフィールドです。
色々と情報はありますが、詳細は割愛して、やり方としてはACFですべて対応可能です。
特定のカテゴリだけで表示させるように設定できるので便利ですね。
軌跡情報であるGPXファイルをページに添付する
これをどうしようかと考えていたのですが、こちらもACFで対応できました。ACFは素晴らしい。
写真を登山記録用のページと関連付ける
アップされた写真をギャラリー挿入でページに紐づけます。
これは標準機能ですね。
見せ方を工夫するならなにか別のプラグインで行ってもいいかもしれません。
サムネイルや地図がプロットされたら写真ページに移動して詳細地図を表示する
こちらは自作プラグインになりますね。
今回は登山情報なので、Googleマップよりも地理院地図の方がいいですね。
地図用JSライブリのLeafletがよさそうです。
ChatGPTに作ってもらいましょう。
プラグイン本体
<?php
// フロントエンドでのスクリプト・スタイルの追加
function my_map_enqueue_scripts() {
wp_enqueue_script('leaflet', 'https://unpkg.com/leaflet@1.7.1/dist/leaflet.js');
wp_enqueue_style('leaflet-css', 'https://unpkg.com/leaflet@1.7.1/dist/leaflet.css');
wp_enqueue_script('my-map-script', plugin_dir_url(__FILE__) . 'js/my-map-script.js', array('leaflet'), '1.0', true);
}
add_action('wp_enqueue_scripts', 'my_map_enqueue_scripts');
// フロントエンドでのみスクリプトを読み込む
function my_map_add_script() {
if (is_single()) {
global $post;
// 投稿に関連する画像とGPXファイルの情報を取得
$images = get_post_meta($post->ID, 'images', true);
$gpx_url = get_post_meta($post->ID, 'gpx_url', true);
// スクリプトに渡すデータ
$script_data = array(
'images' => $images,
'gpx_url' => $gpx_url
);
// データをスクリプトに渡す
wp_localize_script('my-map-script', 'my_map_data', $script_data);
}
}
add_action('wp_enqueue_scripts', 'my_map_add_script');
// カスタムフィールドの座標情報を取得
function get_coordinates() {
global $post;
$coordinates = get_post_meta($post->ID, 'coordinates', true);
if ($coordinates) {
return $coordinates;
}
return false;
}
?>
JS
document.addEventListener('DOMContentLoaded', function () {
var map = L.map('my-map').setView([my_map_data.images[0].latitude, my_map_data.images[0].longitude], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
my_map_data.images.forEach(function (image) {
var marker = L.marker([image.latitude, image.longitude]).addTo(map);
marker.bindPopup('<a href="' + my_map_data.gpx_url + '">View GPX</a><br><img src="' + image.url + '" alt="Image">');
});
});
このままでは動きませんが、これでもかなりヒントになりますね。
準備はここまで。実装は後日行ってみます。
調べてみて
写真のGPS情報は嫌われていて、削除する情報はたくさんありましたが、活用する情報は少なかったです。
10年ぐらい前にフルスクラッチで組んだときは結構錯誤しましたが、今回はWordPress上という前提が返って調べやすくなっていました。しかもAIに仕様を伝えればある程度動作するプログラムは組んでくれます。
まだまだそのまま動かすレベルまでは行きませんが、ワードプレスのプラグインでという条件は結構信頼性の高い回答を返してくれます。
あとACFが優秀すぎます。
自前のCMSで悩んで構築した部分すべて網羅していて、実際によく使っている人が作ったのだなと感心しっぱなしです。