Webサイトにインタラクティブマップを追加する方法 | JavaScriptチュートリアル (2026)
Tutorial

Webサイトにインタラクティブマップを追加する方法 | JavaScriptチュートリアル (2026)

Webサイトにインタラクティブマップを数分で追加できます。マーカー、ポップアップ、ジオコーディング検索、MapAtlasを使用したReact/Next.js統合をカバーするステップバイステップのJavaScriptチュートリアルです。

MapAtlas Team13 min read
#maps#javascript#api#react#next.js#geocoding

すべてのロジスティクスダッシュボード、不動産リスティング、食品配達アプリには共通点があります。マップです。Webサイトにまだマップがない場合は、重要な情報を失っています。ユーザーが位置、近接性、空間的な関係を一目で理解するのに役立つ情報です。

このチュートリアルでは、任意のJavaScriptプロジェクトに完全にインタラクティブなマップを追加する手順を説明します。レンダリングされたマップから始めて、マーカーとポップアップを追加し、ジオコーディングAPIを使用してアドレス検索を接続し、最後にNext.jsにきれいに統合できる本番環境対応のReactコンポーネントを仕上げます。

最終的に構築するもの:

  • APIキーで認証された実際のベクターマップ
  • カスタムポップアップコンテンツ付きのクリック可能なマーカー
  • ジオコーディングを搭載したアドレス検索機能
  • 適切なクリーンアップとNext.js SSR処理を備えた再利用可能なReactコンポーネント
  • 本番環境向けのパフォーマンス最適化チェックリスト

前提条件

開始する前に、以下があることを確認してください:

  • MapAtlas APIキー (無料でサインアップ、クレジットカード不要)。この単一のキーがすべてのMapAtlasサービスを認証します:タイル、ジオコーディング、ルーティング。
  • JavaScriptプロジェクト。プレーンHTML、React、Vue、Svelteなど、すべて機能します。
  • Node.js 18以上(npmでインストールする場合)。

ステップ1:MapAtlas SDKをインストールする

npmを使用してSDKをプロジェクトに組み込みます:

npm install @mapmetrics/mapmetrics-gl

プレーンHTMLページを使用している場合は、CDNリンクを<head>にドロップしてください:

<link rel="stylesheet" href="https://unpkg.com/@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css" />
<script src="https://unpkg.com/@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.js"></script>

CSSのインポートをスキップしないでください。 ないと、マップコントロールとポップアップはスタイルなしでレンダリングされます。機能していますが、視覚的に壊れています。

ステップ2:マップコンテナを作成する

SDKは指定した要素を埋めるため、明示的な高さを持つ<div>が必要です。これは最も一般的なセットアップミスです。コンテナにheight: 0がある場合、マップは初期化されますが、表示されません。

<div id="map" style="width: 100%; height: 500px;"></div>

固定ピクセル値またはビューポートユニット(100vh50vh)の両方が機能します。パーセンテージの高さは、親要素にも定義された高さがある場合にのみ機能します。

ステップ3:最初のインタラクティブマップをレンダリングする

わずか3行の設定で十分です。コンテナ、APIキー付きのスタイルURL、および開始位置です。

import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';

const map = new mapmetricsgl.Map({
  container: 'map',
  style: 'https://tiles.mapatlas.eu/styles/basic/style.json?key=YOUR_API_KEY',
  center: [4.9041, 52.3676],
  zoom: 12,
});

ページを開くと、ドラッグ、スクロール、ピンチしてナビゲートできるベクターマップが表示されます。タイルはMapAtlasサーバーからオンデマンドで読み込まれるため、重いダウンロードは不要です。

マップスタイルを選択する

スタイルURLのパスセグメントを変更して、外観を完全に変更できます:

スタイルURLパス最適な用途
Basic/styles/basic/style.json汎用アプリ
Bright/styles/bright/style.jsonデータ可視化オーバーレイ
Dark/styles/dark/style.jsonダッシュボード、ナイトモード、分析

クイックウィン: 管理パネルと低光環境で使用するツールにダークスタイルを使用してください。目の疲労が軽減され、ヒートマップやルートラインなどのデータレイヤーが背景に対して視覚的に目立ちます。

ステップ4:マップにマーカーとポップアップを追加する

マーカーのないマップは、単なる背景画像です。マーカーは静的なビューを、ユーザーが対話できるものに変えます。

ポップアップ付きの単一マーカー

const popup = new mapmetricsgl.Popup().setHTML(`
  <strong>Amsterdam Central</strong>
  <p>Stationsplein, 1012 AB Amsterdam</p>
`);

new mapmetricsgl.Marker({ color: '#97C70A' })
  .setLngLat([4.9001, 52.3791])
  .setPopup(popup)
  .addTo(map);

マーカーをクリックするとポップアップが開きます。内部に任意のHTMLを配置できます。アドレス、サムネイル、CTAボタンなど、UIが必要とするものは何でもできます。

データから複数のマーカーをプロット

ほとんどの実際のアプリでは、複数のピンが必要です。配列をループして、各エントリのマーカーを作成します:

const locations = [
  { name: 'Amsterdam', coords: [4.9041, 52.3676] },
  { name: 'Rotterdam', coords: [4.4777, 51.9244] },
  { name: 'Utrecht',   coords: [5.1214, 52.0907] },
];

locations.forEach(({ name, coords }) => {
  const popup = new mapmetricsgl.Popup().setHTML(`<strong>${name}</strong>`);
  new mapmetricsgl.Marker({ color: '#97C70A' })
    .setLngLat(coords)
    .setPopup(popup)
    .addTo(map);
});

パフォーマンスに関する注記: 約100~200マーカーを超えると、ズームアウトビューでのレンダリングが顕著に遅くなります。解決策は、GeoJSONソースクラスタリングを有効にすることです(SDKでサポートされています)。低ズームレベルで近くのマーカーをグループ化します。SDKドキュメントでクラスタリング設定を確認してください。

ステップ5:ジオコーディングAPIを使用してアドレス検索を追加する

ジオコーディングAPIは、テキストクエリ(住所、都市名、またはランドマーク)を座標に変換します。これを使用してパンしたり、マークしたり、ルーティングリクエストに入力したりできます。

async function searchAddress(query) {
  const url = new URL('https://api.mapatlas.eu/geocoding/v1/search');
  url.searchParams.set('text', query);
  url.searchParams.set('key', 'YOUR_API_KEY');
  const res  = await fetch(url);
  const data = await res.json();
  if (!data.features.length) return;
  const [lng, lat] = data.features[0].geometry.coordinates;
  const label      = data.features[0].properties.label;
  map.flyTo({ center: [lng, lat], zoom: 14 });
  new mapmetricsgl.Marker({ color: '#97C70A' })
    .setLngLat([lng, lat])
    .setPopup(new mapmetricsgl.Popup().setHTML(`<strong>${label}</strong>`))
    .addTo(map);
}
searchAddress('Rijksmuseum, Amsterdam');

結果はGeoJSONフィーチャーとして返されるため、任意のGeoJSON互換レイヤー、データテーブル、または下流のAPI呼び出しに直接接続できます。

30行未満で実況検索バーを構築する: テキストフィールドのinputイベントにsearchAddressをアタッチし、300msでデバウンスすると、余分な依存関係なしでオートコンプリートスタイルのマップ検索が完成します。

Reactとのインタラクティブマップの統合

再利用可能なマップコンポーネント

マップ初期化をuseEffectでラップして、DOMがマウント後に実行されるようにし、アンマウント時のメモリリークを防ぐクリーンアップ関数を返します:

import { useEffect, useRef } from 'react';
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';

export function MapAtlasMap({ apiKey, center = [4.9041, 52.3676], zoom = 12 }) {
  const containerRef = useRef(null);
  useEffect(() => {
    const map = new mapmetricsgl.Map({
      container: containerRef.current,
      style: `https://tiles.mapatlas.eu/styles/basic/style.json?key=${apiKey}`,
      center, zoom,
    });
    return () => map.remove();
  }, [apiKey]);
  return <div ref={containerRef} style={{ width: '100%', height: '500px' }} />;
}

コンポーネントツリーの任意の場所で使用してください:

<MapAtlasMap apiKey={process.env.NEXT_PUBLIC_MAPATLAS_KEY} center={[4.9041, 52.3676]} zoom={13} />

Next.jsサーバーサイドレンダリングの処理

マップSDKはSSR中に存在しないブラウザAPI(windowdocument)に依存しています。SSRを無効にして、コンポーネントを動的にインポートします:

import dynamic from 'next/dynamic';
const MapAtlasMap = dynamic(
  () => import('./MapAtlasMap').then(m => m.MapAtlasMap),
  { ssr: false, loading: () => (<div style={{ height: 500, background: '#f0f1f3', borderRadius: 12 }} />) }
);

loadingプレースホルダーはマップバンドルがダウンロードされている間、レイアウトを安定させ、累積レイアウトシフト(CLS)を防ぎます。これはユーザー体験とCore Web Vitalsの両方にとって重要です。

本番環境パフォーマンスチェックリスト

リリース前に、これらの最適化を確認してください:

  • フォールドの下のマップを遅延ロードしてください。 IntersectionObserverを使用して、コンテナがビューにスクロールされたときにのみマップを初期化してください。これにより、初期ページロードから約200KBのJavaScriptが遅延します。
  • ベクタータイルに固執してください。 ベクタータイルは任意の画面密度にきれいにスケール変更され、ラスター画像より高速に読み込まれ、追加のサーバーリクエストなしでクライアント側でリスタイルできます。MapAtlasはデフォルトでベクタータイルを提供しています。
  • 大規模なマーカーセットをクラスタリングしてください。 100~200マーカーを超えると、ズームアウトビューでのクラスタリングされていないレンダリングは顕著なフレームドロップを引き起こします。クラスタリングはこれを完全に解決します。
  • APIキーをサーバー側に保たしてください。 キーをパブリックリポジトリにコミットしないでください。環境変数(Next.jsのNEXT_PUBLIC_MAPATLAS_KEY)を使用するか、機密操作についてはバックエンドを通じてリクエストをプロキシしてください。
  • 地域アプリのmaxBoundsを設定してください。 ユーザーが1つの地域のみを気にかけている場合、ビューポートを制限して、その地域外のタイルは要求されません。ネットワークコールが少なくなり、読み込みが速くなります。

次に構築するもの

マップがレンダリング、マーカー表示、アドレス検索、Reactとの統合ができるようになりました。ここから進む方向:

  • ルーティングAPI: 2つの座標間のターンバイターン方向を要求してください。ルートポリライン、総距離、推定所要時間を返します。
  • 等時線API: n分以内に到達可能なすべてのポイントをカバーするポリゴンを生成してください。配達ゾーン、サービスカバレッジマップ、キャッチメントエリア分析に使用されます。
  • マトリックスAPI: 複数のオリジンと宛先間の移動時間と距離を単一のリクエストで計算してください。フリート配車とロジスティクス最適化に不可欠です。

完全なSDKリファレンス、スタイルドキュメンテーション、APIガイドはdocs.mapatlas.xyzで利用できます。


よくある質問

Webサイトにインタラクティブマップを無料で追加できますか?

はい。MapAtlasは、サインアップ時にクレジットカードが不要な無料枠を提供しています。ベクタータイルレンダリング、ジオコーディングAPI、ルーティングAPIが含まれています。これは開発と小規模な本番環境での使用に十分です。

ReactまたはNext.jsアプリにマップを埋め込むにはどうすればよいですか?

マップ初期化をuseEffectフックでラップして、DOMがマウント後に実行されるようにしてください。Next.jsでは、サーバーサイドレンダリングエラーを避けるために、dynamic()ssr: falseで使用してください。両方のアプローチは、このチュートリアルでコピーペースト例でカバーされています。

ベクタータイルとは何ですか、またなぜラスターの代わりに使用する必要があるのですか?

ベクタータイルは、マップフィーチャー(道路、建物、ラベル)を事前にレンダリングされたピクセル画像ではなく、数学的な幾何学として説明しています。任意の解像度に鮮明にスケーリングされ、高速に読み込まれ、追加のサーバーラウンドトリップなしにクライアント側で完全にリスタイルできます。

パフォーマンスが低下する前に何個のマーカーを追加できますか?

レンダリングは通常、低ズームレベルで100~200マーカーを超えると低下します。修正はクラスタリングです。MapAtlas SDKはGeoJSONソースクラスタリングをネイティブにサポートし、低ズームレベルで近くのマーカーをグループ化し、ユーザーがズームインするにつれて展開します。

MapAtlasを使用するのにGIS経験が必要ですか?

いいえ。SDKはGIS専門家ではなく、Webデベロッパー向けに設計されています。座標とズームレベルでマップを初期化し、経度/緯度ペアでマーカーを追加し、ジオコーディングAPIをプレーンテキストで呼び出します。空間データベースやGISツールは不要です。

役に立ちましたか?シェアしてください。

Back to Blog