データ活用&Webアプリ作成プログラム 地形アプリ

JavaScript

はじめに

どうも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>
  1. <!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ピクセルに設定します。これにより、地図が表示される領域のサイズが指定されます。

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: イベントオブジェクト elatlng プロパティは、クリックされた地点の緯度経度情報を持つ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 を使うと、マーカーのアイコンをHTML div 要素で自由にカスタマイズできます。
        • 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: 計算された距離 distancetoFixed(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回にわたりお疲れ様でした!ここまでで皆さんは成長されたと思います。ぜひ他のアプリもご自身で作成し、実力をつけていってください。

ありがとうございました。

タイトルとURLをコピーしました