WordPressからLeafletのポップアップを操作する

事例の概要

地図表示でマーカーを表示するとき、マーカーをクリックするとポップアップ表示するだけでなく、外部のテキストからポップアップを開くことができれば、より便利です(下図)。

この機能を実現するためには、Leaflet側のマーカーのポップアップとWordPressで表示するテキスト表示を動的に連動させることが必要です。

コード量も増えるので、再利用しやすいようにClassに分けて記述することが理想的です。

【お知らせ】
上記の事例3に示すオブジェクト指向(MVCモデル)の使い方については、本書で詳しく解説しています。


コード例

事例1:外部からLeafletを操作

事例の概要

本事例は、「Leaflet 外部からポップアップを開く」をもとに作成しました。

コード例
<body>
    <div id="map_1" style="height: 400px;"></div>
</body>

<p>
<a href="1234map_1"onmouseover="popupOn1(0);">【東京都】</a>
<a href="3456map_1" onmouseover="popupOn1(1);">【千葉県】</a>
<a href="589map_1" onmouseover="popupOn1(2);">【埼玉県】</a>
</p>

<script>
//背景地図
	var osm = new L.tileLayer
		('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    		maxZoom: 19,
    		attribution: "Map data © <a href='https://www.openstreetmap.org/copyright' target='_blank'>OpenStreetMap</a> contributors"
		});
	
	var map_1 = L.map('map_1', {
		layers: [osm],	
		center: [35.6896, 139.6918],
		zoom: 9,
    	zoomControl: true
		});

//マーカー情報
  var markers=[];	
	markers[0]=L.marker([35.6896, 139.6918]).addTo(map_1).bindPopup("東京都");
    markers[1]=L.marker([35.6050, 140.1234]).addTo(map_1).bindPopup("千葉県");
    markers[2]=L.marker([35.8572, 139.6490]).addTo(map_1).bindPopup("埼玉県");

//ポップアップを開く関数
  function popupOn1(id){
    markers[id].openPopup();
  }

</script>
上記コードの実行結果

【東京都】 【千葉県】 【埼玉県】

事例2:WordPressのループ処理とLeafletの連携

事例の概要

本事例は、WordPressのサブクエリーによってテキストデータを動的に表示し、そのループ処理の中でLeafletのマーカー表示を行い、WordPressのテキスト側からLeafletのポップアップ操作を行う事例です。

 冒頭のstatic public $const = array() ;でクラス定数$constを定義します。これは、ループ処理の中でマーカーの情報を一時的に格納するための配列定数です。
 $the_query = new WP_Query($args) ;にてサブクエリーを実行します。
 テキストを表示するWhileループの中で、クラス定数$constに、 緯度($lat),経度( $lon), コンテンツのタイトル($title)などを格納します。以上がPHPの処理です。
 次に、HTMLによる背景地図の設定を行います。
 <div id="map_2" style="height: 400px;"></div>
 最後にLeaflet.jsによる描画処理を行います。

コード例
static public $const = array() ;//クラス定数を定義
	
	public function __construct()
	{

//サブクエリー(テキストを抽出)
	$args = array(
		'post_type' => 'post',
		'tax_query' => array(
		'relation' => 'AND',
			array(
				'taxonomy' => 'region',			
				'field' => 'term_id',
				'terms' => '9790',//中央区
			),
			array(
				'taxonomy' => 'genre',				
				'field' => 'term_id',
				'terms' => '10274',//商店街
			)
		)
	);
	$the_query = new WP_Query($args) ;
//サブループ
	if($the_query->have_posts()){
		While($the_query->have_posts()){
			$the_query->the_post();
				$count++;
//表示(View)部分
	//クラス定数へ緯度経度情報を書き込み
			$array = code40307::$const ;//クラス定数を読み込み
			$num = $count-1 ;
			$id = get_the_ID() ;
			$title = get_post($id)->post_title ;
			$lat = get_post_meta($id, 'latitude', true);//緯度
			$lon = get_post_meta($id, 'longitude', true);//経度
			$array[] = [$id, $lat, $lon, $num, $title];//多次元配列に要素を追加
			code40307::$const = $array ;//クラス定数へ書き込み
	//HTML記述
			?><a class="<?php
				echo $par2->id ;
				echo ' ' ;
				echo 'tag' ;
			?>"href="<?php
				echo get_permalink();
			?>" onmouseover="<?php
				echo 'popupOn2('.$num.');' ;
			?>"><?php
				the_title() ;
				echo "<br>\n" ;
			?></a><?php
					
		}//endwhile
	}//endif

//事物表示
	//クラス定数の呼び出し
	$map_marker_json = json_encode(code40307::$const);
	//地図エリアの設定
	?>
	<body>
    	<div id="map_2" style="height: 400px;"></div>
	</body>

<script>
//背景地図
	var osm = new L.tileLayer
	('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    	maxZoom: 19,
    	attribution: "Map data © <a href='https://www.openstreetmap.org/copyright' target='_blank'>OpenStreetMap</a> contributors"
	});	
	var map_2 = L.map('map_2', {
		layers: [osm],	
		center: [35.664897,139.776624],
		zoom: 15,
    	zoomControl: true
		});

//マーカー表示	
	var array = JSON.parse('<?php echo $map_marker_json; ?>');
	var addmarker2=[];
	var i = 0
	//ループ
	array.forEach(function(id){
    	addmarker2[i]=L.marker([id[1],id[2]]).addTo(map_2).bindPopup(id[4]);
		i++;
	});//endeach

//ポップアップを開く関数
	function popupOn2(id){
		addmarker2[id].openPopup();
	}	
	
</script>
上記コードの実行結果
築地(西仲通り商店街)明治時代の埋め立て工事により出来上がった町。
築地(築地場外市場)寺院の建物と市場の建物がつながっています。

事例3:MVCモデルにLeafletを組み込む

事例の概要

  • 事例2で示したコードは、①WordPressのサブクエリー・サブループによるテキスト表示、②HTMLによる背景地図の表示、③Leaflet.jsによる事物の描画を順に行うものでした。
  • 本事例では、コードの再利用性を高めることを目的に、①②③をそれぞれ別のClassに記述します。

コード例

//外部からLeafletを操作する(オブジエクト指向MVCモデル)
class code40309
{

static public $const = array() ;//クラス定数を定義
	
	public function __construct()
	{
		$args = array(
			'model' => '37694',
			'view' => '40309',
			'pattern_m' => 'Sour',
			'entity_from' => 'Term',
			'entity_to' => 'Post',
			'post_type' => 'post',
			'orand' => 'and',			
			'tax' => array('region','genre'),//地域、ジャンル
			'field_value' => array('9809','10274'),	//台東区、商店街		
		);
		$user = new Controller37694($args) ;
	
		$user = new View40309Map() ;
		
		$user = new View40309Mapmarker() ;
			
	}
}

//表示を行うクラス(View)
class View40309
{
	public function __construct($par)
	{
		$array2 = code40309::$const ;//クラス定数を読み込み
		$num = $par->num ;
		$num = $num-1 ;
		$id = get_the_ID() ;
		$title = get_post($id)->post_title ;
		$lat = get_post_meta($id, 'latitude', true);//緯度
		$lon = get_post_meta($id, 'longitude', true);//経度
		$array2[] = [$id, $lat, $lon, $num, $title];//多次元配列に要素を追加
		code40309::$const = $array2 ;//クラス定数へ書き込み
				
		?><a class="<?php
			echo $par2->id ;
			echo ' ' ;
			echo 'tag' ;
		?>"href="<?php
			echo get_permalink();
		?>" onmouseover="<?php
			echo 'popupOn('.$num.');' ;
		?>"><?php	
			the_title() ;
			echo "<br>\n" ;
		?></a><?php

	}//endfunction
}//endclass


//背景地図を表示するクラス
class View40309Map
{
	public function __construct()
	{
?>
	<body>
    	<div id="map_3" style="height: 400px;"></div>
	</body>

<script>
	var osm = new L.tileLayer
	('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    	maxZoom: 19,
    	attribution: "Map data © <a href='https://www.openstreetmap.org/copyright' target='_blank'>OpenStreetMap</a> contributors"
	});
	
	var map_3 = L.map('map_3', {
		//layers: [osm,old1],
		layers: [osm],	
		center: [35.712364,139.787258],
		zoom: 14,
    	zoomControl: true
		});
</script>

<?php
	}//endfunction
}//endclass

//マーカーを表示するクラス
class View40309Mapmarker
{
	public function __construct()
	{
		$map_marker_json2 = json_encode(code40309::$const);
		?>
<script>
		var array = JSON.parse('<?php echo $map_marker_json2; ?>');
		var addmarker=[];
		var i = 0
		array.forEach(function(id){
    		addmarker[i]=L.marker([id[1],id[2]]).addTo(map_3).bindPopup(id[4]);
			i++;
		});//endeach

  //ポップアップを開く関数
  function popupOn(id){
    addmarker[id].openPopup();
  }

</script>
<?php
	}//endfunction
}//endclass

上記コードの実行結果

浅草橋(おかず横丁)昔ながらの商店街。重厚な看板建築。
上野(アメ横センター地下食品街)日本の中の異国。
浅草(浅草地下街)700円の理髪店。昭和の匂いの残る地下街。
入谷~吉原(せんわ通り)美しい柳並木。水道尻。
入谷~吉原(金美館通り)映画館の名前の通りです。

コメントよろしくお願いします。