GeoJSON を使うと動的にマップにデータを読むこむといったことができます.Google Maps JavaScript API の addGeoJson で GeoJSON を読み込んだときに,スタイルを適用したり,イベントを追加したりする方法を記事にしたいと思います.
GeoJSON
GeoJSON 自体については,以下のようなページを見れば分かります.
データレイヤ | Google Maps JavaScript API | Google Developers
GeoJSON フォーマット仕様
扱えるデータとしては Point,MultiPoint,LineString,MultiLineString,Polygon,MultiPolygon といったものがあります.Google Maps で扱える Circle,Rectangle はありません(どちらもDB上では Polygon として扱えばいいと思います).
読み込むGeoJSON は以下のようなものです.
{
"features": [
{
"geometry": {
"coordinates": [
135.04531860352,
34.206123649908
],
"type": "Point"
},
"properties": {
"color": "#00ff00",
"type": "point",
"description": "cat",
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
134.98489379883,
34.585736286513
],
"type": "Point"
},
"properties": {
"color": "#ff0000",
"type": "point",
"description": "dog",
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
[
[
135.14419555664,
34.532581106491
],
[
135.17852783203,
34.475995767559
],
[
135.23208618164,
34.517872614017
],
[
135.17990112305,
34.582344417658
],
[
135.17303466797,
34.540499988011
],
[
135.14419555664,
34.532581106491
]
]
],
"type": "Polygon"
},
"properties": {
"color": "#0000ff",
"type": "polygon",
"description": "duck",
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
[
134.79537963867,
34.228267666464
],
[
134.81048583984,
34.228835385227
],
[
134.81254577637,
34.246432768532
],
[
134.79537963867,
34.236215380881
]
],
"type": "LineString"
},
"properties": {
"color": "#ff0000",
"type": "polyline",
"description": "wolf",
},
"type": "Feature"
},
],
"type": "FeatureCollection"
}
スタイルの適用
properties
の color
に色を, type
に表示するタイプを入れています.GeoJSON のタイプと,色によって表示するスタイルを切り替えます.マーカー,ポリライン,ポリゴンとそれぞれ処理は違いますが,マーカーの場合の処理は関数化させています.
map.data.setStyle
でスタイルの定義を行います.feature
に各レイヤーのデータが入っていて,feature.getProperty
を使ってレイヤーごとのプロパティを取得しています.
(自分は PHP と非同期通信して動的に生成した GeoJSON を表示させています.もちろん,非同期通信ではない場合でも使えます)
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
// GeoJSON を受け取る
var geojson = JSON.parse(xmlhttp.responseText);
// マップに GeoJSON を追加
// マップにポイントやラインが描画される
// map は initMap() で定義
map.data.addGeoJson(geojson);
// レイヤーのスタイル定義
map.data.setStyle(function(feature) {
if (feature.getProperty('type') === 'point') {
// マーカーの処理は関数を使って処理
return ({
icon: getMarkerColor(feature.getProperty('color')),
});
} else if (feature.getProperty('type') === 'polyline') {
// ポリラインの処理
return ({
strokeColor: feature.getProperty('color'),
strokeWeight: 2,
clickable: true,
zIndex: 1
});
} else {
// ポリゴンの処理
return ({
fillColor: feature.getProperty('color'),
fillOpacity: 0.5,
strokeWeight: 0,
clickable: true,
zIndex: 1
});
}
});
}
}
xmlhttp.open('POST', 'get_geojson.php', true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.timeout = 10000;
xmlhttp.send();
function getMarkerColor(color) {
switch(color) {
case '#ff0000':
markerIcon = 'marker_red.png';
break;
case '#00ff00':
markerIcon = 'marker_green.png';
break;
case '#0000ff':
markerIcon = 'marker_blue.png';
break;
}
return {
url: './icon/' + markerIcon,
scaledSize: new google.maps.Size(21, 32), // scaledSize でリサイズ
};
}
イベントの設定
読み込んだレイヤーにイベントを追加したい場合があると思います.今回はレイヤーに対して,インフォウィンドウ(info windows)を追加する処理を書きます.
event.feature
でレイヤーと同じように feature
を取り出すことができ,プロパティを取得することができます.
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
// GeoJSON を受け取る
var geojson = JSON.parse(xmlhttp.responseText);
// マップに GeoJSON を追加
// マップにポイントやラインが描画される
map.data.addGeoJson(geojson);
// レイヤーのスタイル定義
...(略)
// ユーザがレイヤーをクリックしたときの処理
map.data.addListener('click', function(event) {
// infowindow は initMap() 内で
// infowindow = new google.maps.InfoWindow(); として定義
var description = event.feature.getProperty('description'); // infowindow に入れる内容
infowindow.setContent(description);
infowindow.setPosition(event.latLng); // ここでinfowindowの位置を指定
infowindow.setOptions({pixelOffset: new google.maps.Size(0,-30)});
infowindow.open(map);
});
}
}
xmlhttp.open('POST', 'get_geojson.php', true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.timeout = 10000;
xmlhttp.send();