はじめに
どうもSeiyaです!ここまで3つのアプリを作成して、慣れてきたと思います。最後は少し変化球で地形アプリを作ります!
解説
HTML
HTML
<!DOCTYPE html>
<html>
<head>
<title>2点間距離可視化アプリ</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
<style>
#map { width: 800px; height: 600px; }
</style>
</head>
<body>
<div id="map"></div>
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
<script>
// JavaScriptコードがここに記述されます
</script>
</body>
</html>
<!DOCTYPE html>
:
- これはHTML5の文書型宣言です。ブラウザに対して、この文書がHTML5で記述されていることを伝えます。
2. <html>
:
- HTML文書のルート要素です。すべてのHTML要素は
<html>
タグ内に記述されます。
3. <head>
:
- HTML文書のヘッダ情報を記述する部分です。ここには、ページのタイトル、外部ファイルの読み込み、CSSスタイルなどが記述されます。
<title>2点間距離可視化アプリ</title>
:- ブラウザのタブやウィンドウのタイトルバーに表示されるテキストを設定します。この例では「2点間距離可視化アプリ」というタイトルが設定されています。
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
:- 外部CSSファイルを読み込むためのタグです。
rel="stylesheet"
: このリンクがスタイルシートであることを示します。href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
: 読み込むCSSファイルのURLを指定しています。ここでは、unpkg CDN経由でLeafletライブラリのCSSファイル (leaflet.css) を読み込んでいます。このCSSファイルは、地図の表示スタイルやコントロールのデザインなどを定義しています。
<style> ... </style>
:- HTML文書に直接CSSスタイルを記述するためのタグです。
#map { width: 800px; height: 600px; }
:- CSSセレクタ
#map
は、id
属性がmap
であるHTML要素(後述の<div id="map">
)を指します。 width: 800px;
:#map
要素の幅を800ピクセルに設定します。height: 600px;
:#map
要素の高さを600ピクセルに設定します。これにより、地図が表示される領域のサイズが指定されます。
- CSSセレクタ
4. <body>
:
- HTML文書のコンテンツを記述する部分です。実際にブラウザに表示される内容がここに記述されます。
<div id="map"></div>
:div
要素は、HTMLドキュメントを構造化するための汎用的なコンテナ要素です。id="map"
: このdiv
要素にmap
という一意のIDを付与しています。このIDは、JavaScriptコードからこの要素を特定して操作するために使用されます。Leafletはこのdiv
要素の中に地図を生成して表示します。
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
:- 外部JavaScriptファイルを読み込むためのタグです。
src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
: 読み込むJavaScriptファイルのURLを指定しています。unpkg CDN経由でLeafletライブラリのJavaScriptファイル (leaflet.js) を読み込んでいます。このファイルには、地図生成、マーカー、線描画、イベント処理など、Leafletの主要な機能が含まれています。
<script> ... </script>
:- HTML文書に直接JavaScriptコードを記述するためのタグです。このタグ内に、地図の初期化やイベント処理などのJavaScriptコードが記述されています。次のセクションで詳細に解説します。
JavaScript
HTML
const map = L.map('map').setView([35.681236, 139.767125], 13);
L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png').addTo(map);
let points = [];
let polyline;
let distanceMarker;
map.on('click', (e) => {
points.push(e.latlng);
L.marker(e.latlng).addTo(map);
if (points.length === 2) {
if (polyline) {
map.removeLayer(polyline);
map.removeLayer(distanceMarker);
}
polyline = L.polyline(points, { color: 'red' }).addTo(map);
const distance = points[0].distanceTo(points[1]);
const center = polyline.getBounds().getCenter();
distanceMarker = L.marker(center, {
icon: L.divIcon({
html: `<div style="background: white; padding: 5px;">${distance.toFixed(2)} m</div>`,
iconSize: [80, 20],
iconAnchor: [40, 10]
})
}).addTo(map);
points = [];
}
});
const map = L.map('map').setView([35.681236, 139.767125], 13);
:
L.map('map')
: LeafletライブラリのL.map()
関数を使用して、新しい地図オブジェクトを作成します。引数'map'
は、地図を表示するHTML要素のID(ここでは<div id="map">
)を指定します。これにより、Leafletはid="map"
のdiv
要素を地図のコンテナとして認識します。.setView([35.681236, 139.767125], 13)
:setView()
メソッドは、地図の初期表示の中心座標とズームレベルを設定します。[35.681236, 139.767125]
: 中心座標を緯度経度で指定します。この例では、東京駅周辺の緯度経度 ([緯度, 経度]
) が設定されています。13
: 初期ズームレベルを13に設定します。ズームレベルが大きいほど、地図は詳細に拡大表示されます。
2. L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png').addTo(map);
:
L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png')
: LeafletライブラリのL.tileLayer()
関数を使用して、タイルレイヤー(地図の背景画像)を作成します。'https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png'
: タイル画像のURLテンプレートを指定します。これは、国土地理院が提供している標準地図のタイルURLです。{z}
、{x}
、{y}
は、ズームレベル、X座標、Y座標にそれぞれ置き換えられるプレースホルダーです。Leafletは、表示に必要なタイル画像を自動的にこのURLから取得し、地図上に表示します。
.addTo(map)
: 作成したタイルレイヤーを、先ほど作成したmap
オブジェクトに追加します。これにより、地図に背景画像が表示されるようになります。
3. let points = [];
:
points
という名前の空の配列を宣言します。この配列は、ユーザーが地図上でクリックした地点の座標(緯度経度情報)を格納するために使用されます。
4. let polyline;
:
polyline
という名前の変数を宣言します。この変数は、2つのクリック地点を結ぶポリライン(線)のLeafletオブジェクトを格納するために使用されます。最初はundefined
(未定義)です。
5. let distanceMarker;
:
distanceMarker
という名前の変数を宣言します。この変数は、2点間の距離を表示するマーカーのLeafletオブジェクトを格納するために使用されます。最初はundefined
(未定義)です。
6. map.on('click', (e) => { ... });
:
map.on('click', ... )
: Leafletのmap
オブジェクトに対して、'click'
イベント(地図がクリックされたとき)が発生した際の処理を登録します。(e) => { ... }
: クリックイベントが発生したときに実行される匿名関数(アロー関数)を定義します。引数e
は、イベントオブジェクトで、クリックに関する情報(座標など)が含まれています。points.push(e.latlng);
:e.latlng
: イベントオブジェクトe
のlatlng
プロパティは、クリックされた地点の緯度経度情報を持つLeafletのLatLng
オブジェクトです。points.push(e.latlng)
: クリックされた地点のLatLng
オブジェクトをpoints
配列の末尾に追加します。
L.marker(e.latlng).addTo(map);
:L.marker(e.latlng)
: LeafletライブラリのL.marker()
関数を使用して、新しいマーカーオブジェクトを作成します。引数e.latlng
は、マーカーを配置する座標(クリックされた地点)を指定します。.addTo(map)
: 作成したマーカーをmap
オブジェクトに追加します。これにより、クリックされた地点にマーカーが地図上に表示されます。
if (points.length === 2) { ... }
:points.length === 2
:points
配列の要素数が2になったかどうかをチェックします。つまり、ユーザーが2回クリックしたかどうかを判定しています。2回目のクリック後、2点間の距離計算と表示処理が実行されます。if (polyline) { ... }
:if (polyline)
:polyline
変数が真偽値としてtrue
(つまり、ポリラインオブジェクトがすでに存在するか)を評価します。これは、以前に2点間の距離が計算され、ポリラインと距離マーカーが地図上に表示されているかどうかをチェックしています。map.removeLayer(polyline);
: もし以前のポリラインが存在する場合、Leafletのmap.removeLayer()
メソッドを使用して、地図からポリラインを削除します。これにより、新しい距離計算の際に古い線が地図上に残らないようにします。map.removeLayer(distanceMarker);
: 同様に、以前の距離マーカーが存在する場合、地図から距離マーカーを削除します。
polyline = L.polyline(points, { color: 'red' }).addTo(map);
:L.polyline(points, { color: 'red' })
: LeafletライブラリのL.polyline()
関数を使用して、新しいポリラインオブジェクトを作成します。points
: ポリラインを構成する点の座標配列としてpoints
配列(クリックされた2点の座標)を指定します。{ color: 'red' }
: ポリラインのオプションを指定するオブジェクトです。ここでは、線の色を赤色 ('red'
) に設定しています。
.addTo(map)
: 作成したポリラインをmap
オブジェクトに追加します。これにより、地図上に2点を結ぶ赤い線が表示されます。
const distance = points[0].distanceTo(points[1]);
:points[0].distanceTo(points[1])
: LeafletのLatLng
オブジェクトのdistanceTo()
メソッドを使用して、points
配列の最初の要素 (points[0]
, 1回目のクリック地点) から2番目の要素 (points[1]
, 2回目のクリック地点) までの距離を計算します。この距離はメートル単位で返されます。const distance = ...
: 計算された距離をdistance
という名前の定数に格納します。
const center = polyline.getBounds().getCenter();
:polyline.getBounds()
: ポリラインオブジェクトのバウンズ(範囲)を取得します。バウンズは、ポリラインを囲む最小の矩形領域を表すLeafletのLatLngBounds
オブジェクトです。.getCenter()
:LatLngBounds
オブジェクトのgetCenter()
メソッドを使用して、バウンズの中心座標(緯度経度)を取得します。この中心座標は、距離マーカーをポリラインの中央に配置するために使用されます。const center = ...
: 計算された中心座標をcenter
という名前の定数に格納します。
distanceMarker = L.marker(center, { ... }).addTo(map);
:L.marker(center, { ... })
: LeafletライブラリのL.marker()
関数を使用して、新しいマーカーオブジェクトを作成します。引数center
は、マーカーを配置する座標(ポリラインの中心)を指定します。{ icon: L.divIcon({ ... }) }
: マーカーのオプションを指定するオブジェクトです。ここでは、アイコンとしてL.divIcon
を使用しています。L.divIcon
を使うと、マーカーのアイコンをHTMLdiv
要素で自由にカスタマイズできます。L.divIcon({ ... })
:L.divIcon()
関数を使用して、カスタムアイコンを作成します。html:
<div style=”background: white; padding: 5px;”>${distance.toFixed(2)} m</div>: アイコンとして表示するHTMLコンテンツを指定します。<div style="background: white; padding: 5px;">...</div>
: 背景が白、内側のパディングが5ピクセルのdiv
要素を作成します。${distance.toFixed(2)} m
: 計算された距離distance
をtoFixed(2)
メソッドで小数点以下2桁までフォーマットし、末尾に ” m” (メートル単位)を付けて文字列を生成します。この文字列がdiv
要素の中に表示され、距離のテキストとしてマーカーに表示されます。
iconSize: [80, 20],
: アイコンのサイズを[幅, 高さ]
で指定します。ここでは、幅80ピクセル、高さ20ピクセルに設定しています。iconAnchor: [40, 10]
: アイコンのアンカーポイントを[X座標, Y座標]
で指定します。アンカーポイントは、アイコンのどの部分がマーカーの座標に対応するかを定義します。ここでは、[40, 10]
を指定することで、アイコンの水平方向の中央(幅80ピクセルの半分)、垂直方向の中央(高さ20ピクセルの半分)がマーカーの座標に一致するように設定しています。
.addTo(map)
: 作成した距離マーカーをmap
オブジェクトに追加します。これにより、地図上に距離が表示されたマーカーが表示されます。
points = [];
:points
配列を空にリセットします。これにより、次の距離計算のために新しい2点のクリックを待つ状態に戻ります。
おわりに
4回にわたりお疲れ様でした!ここまでで皆さんは成長されたと思います。ぜひ他のアプリもご自身で作成し、実力をつけていってください。
ありがとうございました。