<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>GeoJSON  |  takeHo（たけほ）のへなちょこ台帳</title>
	<atom:link href="https://blog.takeho.com/tag/geojson/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.takeho.com</link>
	<description>いわゆる自由帳ってところです。</description>
	<lastBuildDate>Thu, 09 Oct 2025 04:57:23 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6</generator>

<image>
	<url>https://blog.takeho.com/wp-content/uploads/2024/08/icon-150x150.png</url>
	<title>GeoJSON  |  takeHo（たけほ）のへなちょこ台帳</title>
	<link>https://blog.takeho.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>観光地マップ構築チュートリアル — HTML／JavaScriptで始めるインタラクティブ地図アプリ</title>
		<link>https://blog.takeho.com/tourist-map-building-tutorial-interactive-map-apps-using-html-javascript-tourist-map-building-tutorial-interactive-map-apps-using-html-javascript/</link>
					<comments>https://blog.takeho.com/tourist-map-building-tutorial-interactive-map-apps-using-html-javascript-tourist-map-building-tutorial-interactive-map-apps-using-html-javascript/#respond</comments>
		
		<dc:creator><![CDATA[たけほ]]></dc:creator>
		<pubDate>Thu, 09 Oct 2025 11:51:00 +0000</pubDate>
				<category><![CDATA[OpenStreetMap]]></category>
		<category><![CDATA[GeoJSON]]></category>
		<category><![CDATA[Leaflet]]></category>
		<guid isPermaLink="false">https://blog.takeho.com/?p=1372</guid>

					<description><![CDATA[まえがき 「Googleマップを使えば、どんな地図アプリでも簡単に作れる」——そう思っている人は、意外と多いのではないでしょうか。 確かに、Google Maps API は高機能で、商用サイトでも広く使われています。し [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h4 class="wp-block-heading"><span id="toc1">まえがき</span></h4>



<p>「Googleマップを使えば、どんな地図アプリでも簡単に作れる」<br>——そう思っている人は、意外と多いのではないでしょうか。</p>



<p>確かに、Google Maps API は高機能で、商用サイトでも広く使われています。<br>しかし最近では、「地図をもっと自由に」「コストを抑えて」「独自のデザインで」活用したいというニーズが高まっています。</p>



<p>そこで注目されているのが、<strong>オープンソースの地図技術「OpenStreetMap（OSM）」</strong> と、<br>軽量な JavaScript ライブラリ <strong>Leaflet.js（リーフレット）</strong> の組み合わせです。</p>



<p>Leaflet は地図アプリ開発の“定番フレームワーク”として世界中で利用されており、<br>たった数行のコードで美しい地図を表示できます。<br>しかも、OSMのオープンデータを使えば無料で地図を提供できるため、<br>小規模なサイトや個人プロジェクト、自治体・観光協会の案内ページなどに最適です。</p>



<p>今回のチュートリアルでは、<br>「観光地をマップ上に可視化し、ジャンル別に表示・非表示を切り替え、<br>さらにルート表示まで行えるインタラクティブな地図アプリ」を<br><strong>HTML・CSS・JavaScriptだけで構築する</strong>方法を解説します。</p>



<p>基本から応用までのステップを、<br>実際のコードサンプルとともに丁寧に追っていくので、<br>プログラミング初心者でも最後まで作りきれる内容です。</p>



<p>このチュートリアルを終える頃には、<br>あなたも <strong>「自分の街を自分の手で描く」</strong> 地図クリエイターになっているはずです。</p>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-2"><label class="toc-title" for="toc-checkbox-2">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><ol><ol><li><a href="#toc1" tabindex="0">まえがき</a></li></ol></li></ol></li><li><a href="#toc2" tabindex="0">はじめに</a><ol><li><a href="#toc3" tabindex="0">なぜ Leaflet + OpenStreetMap なのか</a></li><li><a href="#toc4" tabindex="0">本チュートリアルで作るもののゴール</a></li><li><a href="#toc5" tabindex="0">前提知識・対象読者</a></li></ol></li><li><a href="#toc6" tabindex="0"> Leaflet と OpenStreetMap の基礎知識</a><ol><li><a href="#toc7" tabindex="0">Leaflet とは何か／特徴・利点</a></li><li><a href="#toc8" tabindex="0">OpenStreetMap の概要と利用の注意点</a></li><li><a href="#toc9" tabindex="0">タイルサーバー（地図地図タイル）の仕組み</a></li></ol></li><li><a href="#toc10" tabindex="0">開発環境の準備</a><ol><li><a href="#toc11" tabindex="0">ディレクトリ構成</a></li><li><a href="#toc12" tabindex="0">HTML, CSS, JavaScript ファイルのひな形</a></li><li><a href="#toc13" tabindex="0">Leaflet の読み込み（CDN／npm）</a></li><li><a href="#toc14" tabindex="0">CSSで地図 div に高さ確保</a></li></ol></li><li><a href="#toc15" tabindex="0">地図を表示する（ベースマップ設定）</a><ol><li><a href="#toc16" tabindex="0">地図初期表示位置とズームレベルの設定</a></li><li><a href="#toc17" tabindex="0">OpenStreetMap タイルの追加</a></li><li><a href="#toc18" tabindex="0">属性表示（Attribution 表示）</a></li><li><a href="#toc19" tabindex="0">タイルサービス利用の注意（利用規約、負荷、キャッシュなど）</a></li></ol></li><li><a href="#toc20" tabindex="0">マーカー配置とポップアップ表示</a><ol><li><a href="#toc21" tabindex="0">単一マーカーの追加とポップアップ</a></li><li><a href="#toc22" tabindex="0">複数マーカーを配列で管理して追加</a></li><li><a href="#toc23" tabindex="0">カスタムアイコンを使う</a></li><li><a href="#toc24" tabindex="0">ポップアップ内に HTML やリンクを入れる</a></li></ol></li><li><a href="#toc25" tabindex="0">GeoJSON データの読み込みと表示</a><ol><li><a href="#toc26" tabindex="0">GeoJSON とは何か</a></li><li><a href="#toc27" tabindex="0">GeoJSON を使って観光スポット情報を保持する設計</a></li><li><a href="#toc28" tabindex="0">L.geoJSON() による読み込みとマップへの配置</a></li><li><a href="#toc29" tabindex="0">onEachFeature によるポップアップバインド</a></li><li><a href="#toc30" tabindex="0">スタイリング（スタイル関数）</a></li></ol></li><li><a href="#toc31" tabindex="0">レイヤー制御、グループ化、絞り込み機能</a><ol><li><a href="#toc32" tabindex="0">L.layerGroup／L.featureGroup の活用</a></li><li><a href="#toc33" tabindex="0">コントロール（レイヤー切り替え）を追加</a></li><li><a href="#toc34" tabindex="0">UI制御でカテゴリごとに絞る</a></li><li><a href="#toc35" tabindex="0">フィルタリング機能の応用</a></li></ol></li><li><a href="#toc36" tabindex="0">ルート表示・ナビゲーション機能（応用）</a><ol><li><a href="#toc37" tabindex="0">ルート API の選定</a></li><li><a href="#toc38" tabindex="0">ルート取得リクエスト</a></li><li><a href="#toc39" tabindex="0">GeoJSON によるルート描画</a></li><li><a href="#toc40" tabindex="0">出発地・目的地の入力フォーム</a></li><li><a href="#toc41" tabindex="0">複数ルート・案内表示</a></li></ol></li><li><a href="#toc42" tabindex="0">インタラクティブ性を高める工夫</a><ol><li><a href="#toc43" tabindex="0">クリック・ズームイベントの活用</a></li><li><a href="#toc44" tabindex="0">現在地取得と追従</a></li><li><a href="#toc45" tabindex="0">クラスター化</a></li><li><a href="#toc46" tabindex="0">UX 改善の小技</a></li><li><a href="#toc47" tabindex="0">スマホ対応のポイント</a></li></ol></li><li><a href="#toc48" tabindex="0">パフォーマンスと最適化</a><ol><li><a href="#toc49" tabindex="0">タイルキャッシュ・CDN</a></li><li><a href="#toc50" tabindex="0">GeoJSON の軽量化</a></li><li><a href="#toc51" tabindex="0">レンダリング最適化</a></li><li><a href="#toc52" tabindex="0">ズームレベル制限</a></li><li><a href="#toc53" tabindex="0">レイヤー遅延読み込み</a></li></ol></li><li><a href="#toc54" tabindex="0">デプロイと運用上の注意点</a><ol><li><a href="#toc55" tabindex="0">HTTPS 必須</a></li><li><a href="#toc56" tabindex="0">タイルサーバーの選択</a></li><li><a href="#toc57" tabindex="0">APIキー管理</a></li><li><a href="#toc58" tabindex="0">モニタリングとログ</a></li><li><a href="#toc59" tabindex="0">著作権とライセンス表記</a></li></ol></li><li><a href="#toc60" tabindex="0">完成例と拡張アイデア</a><ol><li><a href="#toc61" tabindex="0">完成例イメージ</a></li><li><a href="#toc62" tabindex="0">拡張アイデア</a></li><li><a href="#toc63" tabindex="0">活用ケース</a></li></ol></li><li><a href="#toc64" tabindex="0">まとめと次のステップ</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc2">はじめに</span></h2>



<h3 class="wp-block-heading"><span id="toc3">なぜ Leaflet + OpenStreetMap なのか</span></h3>



<p>Web上で地図を扱いたいとき、Google Maps や Mapbox など選択肢は多くあります。しかし、以下の理由から <strong>Leaflet + OpenStreetMap（OSM）</strong> の組み合わせは非常に魅力的です：</p>



<ul class="wp-block-list">
<li><strong>オープン性</strong>：Leaflet は軽量なオープンソース JavaScript ライブラリです 。</li>



<li><strong>ライセンス自由度</strong>：OpenStreetMap のデータはオープンライセンスであり、商用利用も可能。ただし適切な属性表示（attribution 表示）は必要です。</li>



<li><strong>軽量で拡張性あり</strong>：Leaflet 自体は小さく、プラグインも豊富。必要な機能だけを追加できる柔軟性があります。</li>



<li><strong>コミュニティと事例の豊富さ</strong>：多くのサイトやシステムで使われており、事例や情報がネット上に多くあります 。</li>



<li><strong>タイルソースを選べる自由</strong>：OSM以外のタイルソースも使える設計で、見た目／性能の選択肢が拡がります。</li>
</ul>



<p>とはいえ、デメリットもあります。たとえば、タイル提供元の制約（過剰なリクエスト制限やキャッシュ制御など）、ルート検索 API の別構築、地図データの更新・同期、負荷分散など運用上の考慮は必要です。</p>



<p>このチュートリアルでは、それらを踏まえつつも「観光地マップを自前で作る」ための実践手順をできるだけ丁寧に解説します。</p>



<h3 class="wp-block-heading"><span id="toc4">本チュートリアルで作るもののゴール</span></h3>



<p>最終的には、次のような機能を備えた「観光地マップアプリ」を作ることを目指します：</p>



<ul class="wp-block-list">
<li>都道府県や都市などの地図中心表示</li>



<li>観光スポット（地点）を GeoJSON 形式で管理</li>



<li>マーカーでスポットを配置し、クリックで名称・説明・画像などをポップアップ表示</li>



<li>観光ジャンル別に表示を絞る UI 制御</li>



<li>出発地／目的地を指定して、地図上にルートを描画</li>



<li>モバイル対応、インタラクティブな UX</li>



<li>高速化・最適化を意識した実装</li>
</ul>



<p>この記事を通じて「地図を扱う基本」「GeoJSON を使ったデータ構造」「インタラクティブ操作の実装法」「運用上の注意点」などを体系的に学べるように設計します。</p>



<h3 class="wp-block-heading"><span id="toc5">前提知識・対象読者</span></h3>



<p>本記事は Web フロントエンド（HTML／CSS／JavaScript）の基本的な知識を持つ方向けを対象としています。ただし、Leaflet や地理情報に不慣れな方でも読み進められるよう、逐次説明を入れます。</p>



<p>また、バックエンド技術（サーバーサイド言語、DB 等）は深く触れませんが、GeoJSON を返す API 設計などについては軽く触れる場面があります。</p>



<h2 class="wp-block-heading"><span id="toc6"> Leaflet と OpenStreetMap の基礎知識</span></h2>



<h3 class="wp-block-heading"><span id="toc7">Leaflet とは何か／特徴・利点</span></h3>



<p>Leaflet（リーフレット）は、Web 上でインタラクティブ地図を扱うための軽量 JavaScript ライブラリです。HTML5／CSS3 に対応し、モバイルでも快適に動作する設計です。<a rel="noopener" href="https://leafletjs.com/?utm_source=chatgpt.com" target="_blank">leafletjs.com+2wiki.openstreetmap.org+2</a></p>



<p>主な特徴：</p>



<ul class="wp-block-list">
<li><strong>軽量設計</strong>：基本ライブラリは小さく、必要な機能をプラグインで追加できる</li>



<li><strong>直感的 API</strong>：<code>L.map</code>、<code>L.tileLayer</code>、<code>L.marker</code> といった関数体系が分かりやすい</li>



<li><strong>拡張性</strong>：多くのプラグイン（クラスタリング、ヒートマップ、ルーティング、GeoJSON 操作など）が存在</li>



<li><strong>多様なレイヤー対応</strong>：タイルレイヤー、ベクターレイヤー、GeoJSON、WMS など</li>



<li><strong>イベント対応</strong>：クリック、パン、ズームなど、各種操作に応じたイベントハンドリングが可能</li>
</ul>



<p>一方で、Leaflet は GIS が得意とする高度なジオプロセシング機能（空間クエリ、ジオメトリ演算など）は基本的に含んでおらず、必要な場合は別ライブラリ（Turf.js や他 GIS ライブラリ）と組み合わせて使うことが多いです。</p>



<h3 class="wp-block-heading"><span id="toc8">OpenStreetMap の概要と利用の注意点</span></h3>



<p>OpenStreetMap（OSM）は、オープンな地理空間データプロジェクトであり、世界中のユーザーが地図情報を編集・参照できます。地図タイルやデータを自前で利用できる自由度が高い点が魅力です。</p>



<p>ただし、使う際には以下の注意があります：</p>



<ul class="wp-block-list">
<li><strong>タイル提供元の制約</strong>：公式の OSM タイルサーバーは、商用サービスや高トラフィック用途を前提とした提供ではありません。過剰な負荷をかけるとアクセス制限を受ける可能性があります。</li>



<li><strong>キャッシュと CDN</strong>：自分でタイルキャッシュや CDN 配信を検討することが望ましい。</li>



<li><strong>属性表示義務（Attribution）</strong>：地図下部などに「© OpenStreetMap contributors」などの表示が必要です。</li>



<li><strong>データ更新</strong>：OSM データは随時更新されているため、キャッシュや定期更新の戦略を持つとよいです。</li>



<li><strong>利用規約・マナー</strong>：API 利用制限、利用ルール、使途の範囲などを確認して使うこと。</li>
</ul>



<h3 class="wp-block-heading"><span id="toc9">タイルサーバー（地図地図タイル）の仕組み</span></h3>



<p>地図アプリで使われる「タイル（タイル画像）」は、ズームレベル <code>z</code>、X／Y の座標で構成される小さな画像単位の地図ブロックです。ブラウザは必要なズームレベルと範囲に応じて適切なタイル画像をリクエストし、地図全体を構成します。</p>



<p>Leaflet では、以下のようにタイル URL テンプレートを指定して読み込むことができます。</p>



<pre class="wp-block-code"><code>L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  maxZoom: 19,
  attribution: '&amp;copy; &lt;a href="https://www.openstreetmap.org/copyright">OpenStreetMap&lt;/a> contributors'
}).addTo(map);</code></pre>



<p>上記の <code><strong>{z}</strong></code>、<code><strong>{x}</strong></code>、<code><strong>{y}</strong></code> はズーム／X座標／Y座標にそれぞれ展開されます。<code><strong>{s}</strong></code> はサブドメイン（例：a, b, c）で並列リクエスト分散に使われます。</p>



<p>この方式のおかげで、クライアント側では効率よくタイルをレンダリングでき、必要なタイルのみを逐次取得できる構造になります。</p>



<h2 class="wp-block-heading"><span id="toc10">開発環境の準備</span></h2>



<h3 class="wp-block-heading"><span id="toc11">ディレクトリ構成</span></h3>



<p>まずは手を動かすためのファイル構成を決めましょう。例えば次のような構成がシンプルで扱いやすいです。</p>



<pre class="wp-block-code"><code>/project-root/
  index.html
  css/
    style.css
  js/
    main.js
  data/
    spots.geojson
  assets/
    icons/
    images/
  README.md</code></pre>



<ul class="wp-block-list">
<li><code>index.html</code>：地図アプリ本体ページ</li>



<li><code>css/style.css</code>：地図表示用および追加 UI 用スタイル</li>



<li><code>js/main.js</code>：メインの JavaScript ロジック</li>



<li><code>data/spots.geojson</code>：観光スポット情報を保持する GeoJSON</li>



<li><code>assets/</code>：アイコン画像、スポット画像など</li>
</ul>



<p>このあたりは、ご自身のブログ構成やファイル配置ルールに合わせて調整しても構いません。</p>



<h3 class="wp-block-heading"><span id="toc12">HTML, CSS, JavaScript ファイルのひな形</span></h3>



<p>まず、<code>index.html</code> の基本骨格を作ります。</p>



<pre class="wp-block-code"><code>&lt;!DOCTYPE html>
&lt;html lang="ja">
&lt;head>
  &lt;meta charset="UTF-8" />
  &lt;meta name="viewport" content="width=device-width, initial-scale=1.0" />
  &lt;title>観光地マップ with Leaflet &amp; OSM&lt;/title>
  &lt;!-- Leaflet CSS を読み込む -->
  &lt;link
    rel="stylesheet"
    href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
    integrity="sha512-…（省略）"
    crossorigin=""
  />
  &lt;link rel="stylesheet" href="css/style.css" />
&lt;/head>
&lt;body>
  &lt;h1>観光地マップ&lt;/h1>
  &lt;div id="map">&lt;/div>

  &lt;!-- 必要なら UI エレメント（例：ジャンル選択、ルート入力フォームなど） -->
  &lt;div id="controls">
    &lt;!-- ジャンル選択など -->
  &lt;/div>

  &lt;!-- Leaflet JS を読み込む -->
  &lt;script
    src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
    integrity="sha512-…（省略）"
    crossorigin=""
  >&lt;/script>
  &lt;script src="js/main.js">&lt;/script>
&lt;/body>
&lt;/html></code></pre>



<p><code>css/style.css</code> には最低限、地図 div の高さを確保するスタイルを入れておきます。</p>



<pre class="wp-block-code"><code>html, body {
  margin: 0;
  padding: 0;
  height: 100%;
}

#map {
  width: 100%;
  height: 80vh; /* ブラウザ高さの 80% を地図領域に使う例 */
}

#controls {
  padding: 1em;
  /* 必要に応じて UI 部分のスタイル */
}
js/main.js は後ほどロジックを入れていきます。まずは空の構造だけ作っておきます：

js
コードをコピーする
// main.js

// 初期化処理
function initMap() {
  // 地図生成やマーカー読み込み等をここに書く
}

// ページ読み込み後に実行
window.addEventListener('load', () => {
  initMap();
});</code></pre>



<h3 class="wp-block-heading"><span id="toc13">Leaflet の読み込み（CDN／npm）</span></h3>



<p>上の HTML 例では CDN 版を使う形式を採っていますが、モジュール構成やビルドツールを使っている場合は npm で Leaflet をインストールして取り込む方法でも構いません。</p>



<pre class="wp-block-code"><code>npm install leaflet</code></pre>



<p>そして JavaScript 側（たとえば bundler 環境）で次のように</p>



<pre class="wp-block-code"><code>import L from 'leaflet';
import 'leaflet/dist/leaflet.css';</code></pre>



<p>という形で取り込むやり方です。ただし、この方式を使う場合、アイコン画像パスや CSS 読み込み処理の設定に注意が必要です（バンドル環境に応じた設定）。</p>



<p>このチュートリアルでは、手軽で理解しやすい CDN 読み込み方式を中心に説明を進めます。</p>



<h3 class="wp-block-heading"><span id="toc14">CSSで地図 div に高さ確保</span></h3>



<p>地図を描画する <code>#map</code> 要素には高さがゼロだと表示されないので、必ず CSS で高さを指定する必要があります（vh 単位や固定 px 単位など）。</p>



<p>例として先に示した <code>height: 80vh</code> のような指定や、<code>height: 500px</code> などでも構いません。レスポンシブ対応を考えるなら、<code>@media</code> を使ってスマホ・PCで高さ調整をする方法も後で紹介します。</p>



<h2 class="wp-block-heading"><span id="toc15">地図を表示する（ベースマップ設定）</span></h2>



<p>ここから、実際に地図を画面に表示する手順を進めていきます。</p>



<h3 class="wp-block-heading"><span id="toc16">地図初期表示位置とズームレベルの設定</span></h3>



<p><code>main.js</code> に以下のような基本コードを入れます。</p>



<pre class="wp-block-code"><code>function initMap() {
  // 観光地マップの初期中心位置（例：東京駅周辺）
  const centerLatLng = &#91;35.681236, 139.767125]; // 緯度, 経度
  const initialZoom = 13;

  // 地図オブジェクト生成
  const map = L.map('map').setView(centerLatLng, initialZoom);

  // タイルレイヤー（OSM）を追加
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 19,
    attribution:
      '&amp;copy; &lt;a href="https://www.openstreetmap.org/copyright">OpenStreetMap&lt;/a> contributors',
  }).addTo(map);

  // オプション: 他操作設定
  // map.zoomControl.setPosition('topright');
}</code></pre>



<p>このコードを走らせると、<code>#map</code> の位置に地図が表示され、指定した中心とズームレベルで初期表示されます。</p>



<h3 class="wp-block-heading"><span id="toc17">OpenStreetMap タイルの追加</span></h3>



<p>上記の <code>L.tileLayer(...)</code> が OSM のタイルを地図に読み込む役割です。タイルの URL テンプレートとオプション（<code>maxZoom</code>, <code>attribution</code> など）を指定しています。</p>



<p><code>tlesLayer</code> のオプションでは、以下のような設定がよく使われます：</p>



<ul class="wp-block-list">
<li><code>maxZoom</code>: 最大ズームレベル</li>



<li><code>minZoom</code>: 最小ズームレベル</li>



<li><code>attribution</code>: 地図著作権表示</li>



<li><code>subdomains</code>: <code>{s}</code> に使うサブドメイン配列（例：<code>['a','b','c']</code>）</li>



<li><code>tileSize</code>, <code>zoomOffset</code>：タイルの仕様調整</li>
</ul>



<h3 class="wp-block-heading"><span id="toc18">属性表示（Attribution 表示）</span></h3>



<p>タイルプロバイダー（この場合 OSM）には著作権表示義務（Attribution）があるため、地図下部などに必ず表示を行います。Leaflet の <code>attribution</code> オプションを使って設定可能です。</p>



<pre class="wp-block-code"><code>attribution:
  '&amp;copy; &lt;a href="https://www.openstreetmap.org/copyright">OpenStreetMap&lt;/a> contributors'</code></pre>



<p>このように HTML タグを使って地図表示元へのリンクを含む表記を記述します。</p>



<h3 class="wp-block-heading"><span id="toc19">タイルサービス利用の注意（利用規約、負荷、キャッシュなど）</span></h3>



<ul class="wp-block-list">
<li><strong>公式 OSM タイルサーバーの制約</strong><br>多くのプロジェクトでは、公式 OSM タイルサーバー（<code>tile.openstreetmap.org</code>）をそのまま商用サイトで使うのは推奨されません。過剰リクエスト時には制限が課される可能性があります。</li>



<li><strong>代替タイル提供サービス</strong><br>Mapbox、Maptiler、Stadia Maps、Carto 等、有償または無料プランのタイルサービスを併用する手段があります。</li>



<li><strong>キャッシュ／CDN 利用</strong><br>プロキシキャッシュや CDN を使って、タイル取得負荷を軽減する構成が望まれます。</li>



<li><strong>リクエスト節約</strong><br>不要なズームレベルでの読み込みを制限したり、不要なレイヤー読み込みを遅延化（Lazy Load）する工夫が重要です。</li>
</ul>



<h2 class="wp-block-heading"><span id="toc20">マーカー配置とポップアップ表示</span></h2>



<p>次は観光スポットをマーカーで表示し、クリック時に詳細情報を表示するようにします。</p>



<h3 class="wp-block-heading"><span id="toc21">単一マーカーの追加とポップアップ</span></h3>



<p>まずは簡単に、ひとつのマーカーを追加してポップアップを表示する例です。</p>



<pre class="wp-block-code"><code>// 地図 map が生成済とする
const marker = L.marker(&#91;35.6895, 139.6917]).addTo(map);
marker.bindPopup('&lt;b>東京タワー&lt;/b>&lt;br>東京の有名な展望塔です。');</code></pre>



<p><code>.bindPopup(...)</code> でマーカーポップアップ内容を指定できます。<code>.openPopup()</code> をつけると初期表示時からポップアップ展開できます。</p>



<h3 class="wp-block-heading"><span id="toc22">複数マーカーを配列で管理して追加</span></h3>



<p>観光スポットが複数ある場合は、JavaScript の配列で管理し、ループでマーカーを生成する形が一般的です。</p>



<pre class="wp-block-code"><code>const spots = &#91;
  {
    name: '東京タワー',
    desc: '東京の有名な展望塔です。',
    lat: 35.65858,
    lng: 139.745433,
  },
  {
    name: '浅草寺',
    desc: '浅草の歴史あるお寺。',
    lat: 35.714765,
    lng: 139.796655,
  },
  // 他スポット…
];

spots.forEach((spot) => {
  const marker = L.marker(&#91;spot.lat, spot.lng]).addTo(map);
  marker.bindPopup(`&lt;b>${spot.name}&lt;/b>&lt;br>${spot.desc}`);
});</code></pre>



<p>この形式であればスポット数が増えても拡張しやすくなります。</p>



<h3 class="wp-block-heading"><span id="toc23">カスタムアイコンを使う</span></h3>



<p>マーカーアイコンをオリジナルの画像に変更する例</p>



<pre class="wp-block-code"><code>const customIcon = L.icon({
  iconUrl: 'assets/icons/spot-icon.png',
  iconSize: &#91;32, 37], // 幅・高さ（px）
  iconAnchor: &#91;16, 37], // アイコンの尖った位置（マーカー先端）を基準点に
});

spots.forEach((spot) => {
  const marker = L.marker(&#91;spot.lat, spot.lng], { icon: customIcon }).addTo(map);
  marker.bindPopup(`&lt;b>${spot.name}&lt;/b>&lt;br>${spot.desc}`);
});</code></pre>



<p>アイコン画像のパスやサイズ調整を適切に行うことで、見栄えを改善できます。</p>



<h3 class="wp-block-heading"><span id="toc24">ポップアップ内に HTML やリンクを入れる</span></h3>



<p>ポップアップには HTML を自由に含められます。</p>



<pre class="wp-block-code"><code>marker.bindPopup(`
  &lt;div>
    &lt;h3>${spot.name}&lt;/h3>
    &lt;img src="assets/images/${spot.image}" alt="${spot.name}" width="200">
    &lt;p>${spot.desc}&lt;/p>
    &lt;a href="${spot.url}" target="_blank">公式サイトへ&lt;/a>
  &lt;/div>
`);</code></pre>



<p>画像やリンク、スタイルを入れることで、ユーザにとってリッチな情報を提示できます。</p>



<h2 class="wp-block-heading"><span id="toc25">GeoJSON データの読み込みと表示</span></h2>



<p>多数のスポット情報を管理するには、GeoJSON 形式でデータを扱うのが便利です。</p>



<h3 class="wp-block-heading"><span id="toc26">GeoJSON とは何か</span></h3>



<p>GeoJSON は地理空間情報を JSON で記述するデータフォーマットで、点（Point）、線（LineString）、面（Polygon）などを表現できます。属性情報（プロパティ）も含められるため、地図アプリでは扱いやすい形式です。</p>



<p>GeoJSON の構造例（観光スポット用）：</p>



<pre class="wp-block-code"><code>{
  "type": "FeatureCollection",
  "features": &#91;
    {
      "type": "Feature",
      "properties": {
        "name": "東京タワー",
        "desc": "東京の有名な展望塔です。",
        "image": "tokyo-tower.jpg",
        "url": "https://www.tokyotower.co.jp/"
      },
      "geometry": {
        "type": "Point",
        "coordinates": &#91;139.745433, 35.65858]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "name": "浅草寺",
        "desc": "浅草の歴史あるお寺。",
        "image": "sensouji.jpg",
        "url": "https://www.senso-ji.jp/"
      },
      "geometry": {
        "type": "Point",
        "coordinates": &#91;139.796655, 35.714765]
      }
    }
    // …他のスポット
  ]
}</code></pre>



<p>注意：Leaflet は緯度・経度順 <code>[lat, lon]</code> ではなく、GeoJSON の座標は <code>[longitude, latitude]</code> の順で定義する点に注意する必要があります。</p>



<h3 class="wp-block-heading"><span id="toc27">GeoJSON を使って観光スポット情報を保持する設計</span></h3>



<p><code>data/spots.geojson</code> に上記の形式でスポットを記述しておき、クライアント側でこれを取得してマップ上にレンダリングします。この設計により、データと表示ロジックを分離でき、後からスポットの追加・更新が容易になります。</p>



<h3 class="wp-block-heading"><span id="toc28">L.geoJSON() による読み込みとマップへの配置</span></h3>



<p><code>main.js</code> に以下のようなコードを追加します。</p>



<pre class="wp-block-code"><code>function initMap() {
  // …地図初期化処理…

  // GeoJSON をフェッチして表示
  fetch('data/spots.geojson')
    .then((resp) => resp.json())
    .then((geojson) => {
      L.geoJSON(geojson, {
        onEachFeature: onEachSpotFeature,
      }).addTo(map);
    })
    .catch((err) => console.error('GeoJSON 読み込みエラー:', err));
}

// 各 Feature に対する処理
function onEachSpotFeature(feature, layer) {
  if (feature.properties &amp;&amp; feature.properties.name) {
    const popupContent = `
      &lt;div>
        &lt;h3>${feature.properties.name}&lt;/h3>
        &lt;p>${feature.properties.desc}&lt;/p>
        ${feature.properties.image ? `&lt;img src="assets/images/${feature.properties.image}" width="200" />` : ''}
        ${feature.properties.url ? `&lt;br>&lt;a href="${feature.properties.url}" target="_blank">公式サイト&lt;/a>` : ''}
      &lt;/div>
    `;
    layer.bindPopup(popupContent);
  }
}</code></pre>



<p>このように、GeoJSON の各 Feature を <code>L.geoJSON</code> で読み込むと、自動的に適切な Leaflet レイヤー（この場合は点 → マーカー）として変換され、<code>onEachFeature</code> 関数でポップアップ処理などを設定できます。</p>



<h3 class="wp-block-heading"><span id="toc29">onEachFeature によるポップアップバインド</span></h3>



<p><code>onEachFeature(feature, layer)</code> 関数は、GeoJSON の各 Feature に対して呼ばれ、<code>layer</code>（Leaflet 上のレイヤー）にポップアップやイベントをバインドできます。前述の例では <code>layer.bindPopup(...)</code> を使っています。</p>



<p>この関数をもっと拡張して、クリックイベントや <code>mouseover</code>／<code>mouseout</code> イベントなども設定できます。</p>



<h3 class="wp-block-heading"><span id="toc30">スタイリング（スタイル関数）</span></h3>



<p>GeoJSON のレイヤーにスタイルを与えることも可能ですが、点（Point）ではマーカーアイコンで代替することが多く、線・面（Polyline／Polygon）を描く用途で有効です。</p>



<p>たとえば、線（観光ルート）やエリア（観光エリア範囲）を GeoJSON で定義してスタイルを指定する例：</p>



<pre class="wp-block-code"><code>L.geoJSON(geojsonLineOrPolygon, {
  style: function(feature) {
    return {
      color: feature.properties.color || 'blue',
      weight: feature.properties.weight || 3,
      opacity: feature.properties.opacity || 0.7,
    };
  },
  onEachFeature: function(feature, layer) {
    if (feature.properties &amp;&amp; feature.properties.name) {
      layer.bindPopup(feature.properties.name);
    }
  },
}).addTo(map);</code></pre>



<p>観光地マップでは、線／エリアを使う機会はルート表示やエリアハイライトといった拡張部分で出てきます。</p>



<h2 class="wp-block-heading"><span id="toc31">レイヤー制御、グループ化、絞り込み機能</span></h2>



<h3 class="wp-block-heading"><span id="toc32">L.layerGroup／L.featureGroup の活用</span></h3>



<p>観光地マップでは、スポットの種類（例：史跡・自然・グルメなど）ごとにマーカーをまとめたい場面があります。Leaflet にはそのための機能として <code>L.layerGroup()</code> と <code>L.featureGroup()</code> が用意されています。</p>



<ul class="wp-block-list">
<li><strong><code>L.layerGroup()</code></strong>：単純に複数レイヤー（マーカーなど）をまとめるためのコンテナ。</li>



<li><strong><code>L.featureGroup()</code></strong>：<code>L.layerGroup</code> に加え、グループ全体にイベント（クリック、mouseover など）を設定できる。</li>
</ul>



<pre class="wp-block-preformatted">const historicalGroup = L.layerGroup();<br>const foodGroup = L.layerGroup();<br>const natureGroup = L.layerGroup();<br><br>// 各カテゴリに属するマーカーを追加<br>L.marker([35.71, 139.79]).bindPopup('浅草寺').addTo(historicalGroup);<br>L.marker([35.67, 139.77]).bindPopup('築地市場').addTo(foodGroup);<br>L.marker([35.68, 139.73]).bindPopup('日比谷公園').addTo(natureGroup);<br><br>// デフォルトでは全部表示<br>historicalGroup.addTo(map);<br>foodGroup.addTo(map);<br>natureGroup.addTo(map);</pre>



<h3 class="wp-block-heading"><span id="toc33">コントロール（レイヤー切り替え）を追加</span></h3>



<p>Leaflet には地図上でレイヤーを切り替えるUI部品が標準で用意されています。<br>次のようにして、チェックボックス式のレイヤーコントロールを追加できます。</p>



<pre class="wp-block-code"><code>const baseMaps = {
  "OpenStreetMap": osmLayer,
  "OSM Humanitarian": humanitarianLayer,
};

const overlayMaps = {
  "史跡": historicalGroup,
  "グルメ": foodGroup,
  "自然": natureGroup
};

L.control.layers(baseMaps, overlayMaps).addTo(map);</code></pre>



<p>これで地図右上にレイヤー選択ウィジェットが追加され、ユーザが表示・非表示を切り替えられるようになります。観光情報のカテゴリ分けに最適です。</p>



<h3 class="wp-block-heading"><span id="toc34">UI制御でカテゴリごとに絞る</span></h3>



<p>レイヤー切り替えの代わりに、HTML の <code>&lt;select&gt;</code> や <code>&lt;button&gt;</code> を使ってカテゴリごとに絞る方式もよく使われます。</p>



<pre class="wp-block-preformatted">&lt;select id="category"><br>  &lt;option value="all">すべて&lt;/option><br>  &lt;option value="historical">史跡&lt;/option><br>  &lt;option value="food">グルメ&lt;/option><br>  &lt;option value="nature">自然&lt;/option><br>&lt;/select></pre>



<p>JavaScript 側ではイベントを監視して絞り込みを制御します。</p>



<pre class="wp-block-code"><code>document.getElementById('category').addEventListener('change', (e) => {
  const val = e.target.value;
  &#91;historicalGroup, foodGroup, natureGroup].forEach(g => map.removeLayer(g));
  if (val === 'all' || val === 'historical') historicalGroup.addTo(map);
  if (val === 'all' || val === 'food') foodGroup.addTo(map);
  if (val === 'all' || val === 'nature') natureGroup.addTo(map);
});</code></pre>



<p>UIと連携することで、より自然な操作感を実現できます。</p>



<h3 class="wp-block-heading"><span id="toc35">フィルタリング機能の応用</span></h3>



<p>GeoJSON データを大量に扱う場合、クライアント側でフィルタリングしてから描画する方法も有効です。</p>



<pre class="wp-block-code"><code>fetch('data/spots.geojson')
  .then(res => res.json())
  .then(json => {
    const filtered = json.features.filter(f => f.properties.category === 'historical');
    L.geoJSON({ type: 'FeatureCollection', features: filtered }).addTo(map);
  });</code></pre>



<p>これにより、データを都度再描画する形で軽量に扱うこともできます。</p>



<h2 class="wp-block-heading"><span id="toc36">ルート表示・ナビゲーション機能（応用）</span></h2>



<h3 class="wp-block-heading"><span id="toc37">ルート API の選定</span></h3>



<p>Leaflet 自体には経路探索機能はありません。そのため、外部のルーティングサービスを利用します。代表的なものとして</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>サービス名</th><th>特徴</th><th>無料枠</th></tr></thead><tbody><tr><td><strong>OpenRouteService</strong></td><td>OSM データを基にしたルート検索</td><td>1日あたり多数</td></tr><tr><td><strong>OSRM</strong></td><td>高速なオープンソースルータ</td><td>自前ホスティング可</td></tr><tr><td><strong>GraphHopper</strong></td><td>商用利用も可能なAPI</td><td>月間制限あり</td></tr></tbody></table></figure>



<h3 class="wp-block-heading"><span id="toc38">ルート取得リクエスト</span></h3>



<p>OpenRouteService の例を見てみましょう。<br>以下のようなエンドポイントに GET リクエストを送信します。</p>



<pre class="wp-block-code"><code>https:&#47;&#47;api.openrouteservice.org/v2/directions/foot-walking?api_key=YOUR_KEY&amp;start=139.745433,35.65858&amp;end=139.796655,35.714765</code></pre>



<p>返却される JSON は GeoJSON 形式のルート情報を含んでおり、これを <code>L.geoJSON()</code> で表示可能です。</p>



<h3 class="wp-block-heading"><span id="toc39">GeoJSON によるルート描画</span></h3>



<pre class="wp-block-code"><code>fetch(url)
  .then(res => res.json())
  .then(data => {
    const route = data.features&#91;0];
    L.geoJSON(route, {
      style: {
        color: 'red',
        weight: 4
      }
    }).addTo(map);
  });</code></pre>



<p>これで、2地点間のルートが地図上に赤いラインで表示されます。</p>



<h3 class="wp-block-heading"><span id="toc40">出発地・目的地の入力フォーム</span></h3>



<p>ユーザーに自由に経路を指定させる場合は、HTML フォームを追加します。</p>



<pre class="wp-block-code"><code>&lt;input id="start" placeholder="出発地（緯度,経度）">
&lt;input id="end" placeholder="目的地（緯度,経度）">
&lt;button id="routeBtn">ルート表示&lt;/button></code></pre>



<p>ボタンクリックで API にリクエストを送り、ルートを描画する仕組みです。<br>UIを工夫すれば、クリックで地点を選んだり、現在地を自動入力したりもできます。</p>



<h3 class="wp-block-heading"><span id="toc41">複数ルート・案内表示</span></h3>



<p>OpenRouteService などは複数ルート案を返すこともあり、これを切り替えて表示することで利便性を向上できます。<br>さらに、ルートの距離や所要時間をポップアップやサイドバーに表示すれば、簡易ナビとしても機能します。</p>



<h2 class="wp-block-heading"><span id="toc42">インタラクティブ性を高める工夫</span></h2>



<h3 class="wp-block-heading"><span id="toc43">クリック・ズームイベントの活用</span></h3>



<p>Leaflet では地図やマーカーに多数のイベントを設定できます。</p>



<pre class="wp-block-code"><code>map.on('click', function(e) {
  L.popup()
    .setLatLng(e.latlng)
    .setContent(`緯度: ${e.latlng.lat.toFixed(5)}, 経度: ${e.latlng.lng.toFixed(5)}`)
    .openOn(map);
});</code></pre>



<p>地図をクリックした場所の座標を確認できるデバッグ用の機能として便利です。</p>



<h3 class="wp-block-heading"><span id="toc44">現在地取得と追従</span></h3>



<p>ブラウザの Geolocation API を使えば、現在地を取得して地図中心を自動移動できます。</p>



<pre class="wp-block-code"><code>if (navigator.geolocation) {
  navigator.geolocation.getCurrentPosition((pos) => {
    const lat = pos.coords.latitude;
    const lng = pos.coords.longitude;
    map.setView(&#91;lat, lng], 15);
    L.marker(&#91;lat, lng]).addTo(map).bindPopup("現在地");
  });
}</code></pre>



<p>旅行中にスマートフォンで使う観光マップでは特に有用です。</p>



<h3 class="wp-block-heading"><span id="toc45">クラスター化</span></h3>



<p>観光地が数百件を超えると、マーカーが重なり視認性が落ちます。<br><code>leaflet.markercluster</code> プラグインを使うと、近接したマーカーをグループ化してまとめて表示できます。</p>



<pre class="wp-block-code"><code>const markers = L.markerClusterGroup();
spots.forEach((s) => {
  const m = L.marker(&#91;s.lat, s.lng]).bindPopup(s.name);
  markers.addLayer(m);
});
map.addLayer(markers);</code></pre>



<p>クラスターをクリックするとズームして展開され、軽快な操作感が得られます。</p>



<h3 class="wp-block-heading"><span id="toc46">UX 改善の小技</span></h3>



<ul class="wp-block-list">
<li>マウスオーバーでスポット名をツールチップ表示</li>



<li>マーカークリック時にスクロールを抑止</li>



<li><code>flyTo()</code> や <code>panTo()</code> を使ってスムーズに地図中心を移動</li>



<li>ズームや回転をアニメーション化（モバイルでは特に効果的）</li>
</ul>



<h3 class="wp-block-heading"><span id="toc47">スマホ対応のポイント</span></h3>



<p>地図は <code>height: 100vh</code> で全画面表示し、UIボタンは固定配置にします。<br>スマホではポップアップサイズを調整し、誤タップを防ぐ余白を設けると良いでしょう。</p>



<h2 class="wp-block-heading"><span id="toc48">パフォーマンスと最適化</span></h2>



<p>Leaflet は軽量ですが、データ量が多いと描画負荷が上がります。ここでは高速化のポイントを整理します。</p>



<h3 class="wp-block-heading"><span id="toc49">タイルキャッシュ・CDN</span></h3>



<p>タイル画像を自前でキャッシュするか、Maptiler などの CDN タイルを利用することで、レスポンスを大幅に改善できます。</p>



<h3 class="wp-block-heading"><span id="toc50">GeoJSON の軽量化</span></h3>



<ul class="wp-block-list">
<li>不要な属性を削除</li>



<li>緯度経度を小数点4桁程度に丸める</li>



<li>GeoJSON を分割して遅延読み込み</li>
</ul>



<p>これによりデータ転送量を削減できます。</p>



<h3 class="wp-block-heading"><span id="toc51">レンダリング最適化</span></h3>



<p>マーカーが多すぎる場合は、すべてを一度に描画せず、ズームレベルに応じて表示数を制御します。</p>



<pre class="wp-block-code"><code>map.on('zoomend', () =&gt; {
  const zoom = map.getZoom();
  if (zoom &lt; 10) {
    map.removeLayer(detailGroup);
  } else {
    map.addLayer(detailGroup);
  }
});</code></pre>



<h3 class="wp-block-heading"><span id="toc52">ズームレベル制限</span></h3>



<p>あまり細かくズームできる必要がない場合、<code>maxZoom</code> を低めに設定すると、不要なタイルロードを防げます。</p>



<h3 class="wp-block-heading"><span id="toc53">レイヤー遅延読み込み</span></h3>



<p>スクロールやボタン操作で特定エリアに来たときだけデータを読み込む方式（Lazy Load）も有効です。</p>



<h2 class="wp-block-heading"><span id="toc54">デプロイと運用上の注意点</span></h2>



<h3 class="wp-block-heading"><span id="toc55">HTTPS 必須</span></h3>



<p>地図APIやGeolocation APIを利用するには、サイトがHTTPSである必要があります。<br>特に現在地取得はHTTP環境では動作しません。</p>



<h3 class="wp-block-heading"><span id="toc56">タイルサーバーの選択</span></h3>



<p>商用サービスでの安定運用には、次のような代替タイル提供元を検討します。</p>



<ul class="wp-block-list">
<li>Maptiler Cloud</li>



<li>Stadia Maps</li>



<li>Thunderforest</li>



<li>CARTO Basemaps</li>
</ul>



<p>それぞれスタイルや利用制限、価格体系が異なるため、用途に合わせて選定します。</p>



<h3 class="wp-block-heading"><span id="toc57">APIキー管理</span></h3>



<p>OpenRouteService などの外部APIを使う場合は、<code>.env</code> やサーバ側でキーを隠蔽するのが鉄則です。<br>フロントに直接埋め込むと不正利用のリスクが高まります。</p>



<h3 class="wp-block-heading"><span id="toc58">モニタリングとログ</span></h3>



<p>アクセスログやリクエスト数を可視化し、負荷が高い時間帯を把握することでタイル制限を回避しやすくなります。</p>



<h3 class="wp-block-heading"><span id="toc59">著作権とライセンス表記</span></h3>



<p>地図の下部に OSM のクレジット表記を残すことは必須です。<br>自作タイルを使う場合でも、元データが OSM の場合は「© OpenStreetMap contributors」と明記します。</p>



<h2 class="wp-block-heading"><span id="toc60">完成例と拡張アイデア</span></h2>



<h3 class="wp-block-heading"><span id="toc61">完成例イメージ</span></h3>



<p>完成したマップは、観光地スポットを色分けしたマーカーで表示し、クリックで写真・説明文を表示します。<br>ジャンル別の絞り込みUIと、ルート検索ボタンを併設することで、実用的な観光ナビとして機能します。</p>



<h3 class="wp-block-heading"><span id="toc62">拡張アイデア</span></h3>



<ul class="wp-block-list">
<li><strong>レビュー機能</strong>：各スポットにコメントや評価を追加</li>



<li><strong>写真ギャラリー</strong>：ポップアップにスライダーを埋め込み</li>



<li><strong>オフラインキャッシュ</strong>：PWA対応で一部キャッシュ</li>



<li><strong>多言語化</strong>：Leaflet のラベルやUIを英語・中国語対応</li>



<li><strong>時系列データ</strong>：季節イベントや期間限定情報を時間軸で管理</li>
</ul>



<h3 class="wp-block-heading"><span id="toc63">活用ケース</span></h3>



<ul class="wp-block-list">
<li>自治体や観光協会の案内サイト</li>



<li>イベントマップ（花火大会・祭り）</li>



<li>トレッキング／自転車ルート案内</li>



<li>ショッピングモールや施設内マップ</li>
</ul>



<h2 class="wp-block-heading"><span id="toc64">まとめと次のステップ</span></h2>



<p>Leaflet.js と OpenStreetMap を組み合わせることで、無料かつ柔軟な観光地マップを構築できました。<br>今回のポイントを整理します。</p>



<ol class="wp-block-list">
<li><strong>Leaflet の基礎構造</strong>：<code>L.map()</code> で地図を生成し、<code>L.tileLayer()</code> でOSMタイルを追加。</li>



<li><strong>マーカーとポップアップ</strong>：<code>L.marker()</code> と <code>.bindPopup()</code> で地点情報を視覚化。</li>



<li><strong>GeoJSON の利用</strong>：観光地データを分離し、柔軟に更新可能。</li>



<li><strong>レイヤー管理</strong>：カテゴリごとにグループ化し、ユーザ操作で切り替え。</li>



<li><strong>ルート描画</strong>：外部APIと組み合わせてナビゲーション実装。</li>



<li><strong>パフォーマンスと運用</strong>：キャッシュ、API管理、著作権表記を徹底。</li>
</ol>



<p>Leaflet はプラグインが豊富で、今後さらに機能拡張が可能です。<br>次のステップとしては以下を試すとよいでしょう。</p>



<ul class="wp-block-list">
<li><strong>Leaflet Routing Machine</strong> を使った経路案内</li>



<li><strong>Turf.js</strong> による地理解析（距離計算・範囲抽出）</li>



<li><strong>Leaflet Search</strong> プラグインによる検索機能追加</li>



<li><strong>サーバ連携</strong>：バックエンドから GeoJSON を動的取得</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.takeho.com/tourist-map-building-tutorial-interactive-map-apps-using-html-javascript-tourist-map-building-tutorial-interactive-map-apps-using-html-javascript/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
