JavaScript

JavaScriptで現在地を取得してGoogleマップを移動させる|Geolocation API実装ガイド

みなと

Webサイトやアプリで「現在地を取得して表示する」機能は、地図サービスや店舗検索などでよく見かけます。ですが、いざ自分で実装しようとすると――

UI実装担当
UI実装担当

JavaScriptでどうやって現在位置を取得すればいいの?
地図に反映するにはどうすればいいの?

そんな疑問を持つ方も多いのではないでしょうか。

現在地の取得は意外とシンプル

実は、ブラウザにはGeolocation APIという仕組みが用意されており、これを使えばユーザーの緯度・経度を簡単に取得できます。特別なライブラリを使わなくても、数行のJavaScriptだけで位置情報を扱うことができるのです。

Googleマップへの反映は別の仕組み

一方で、取得した位置を地図上に表示したい場合は、Google Maps JavaScript API を使います。

  • Geolocation API → 現在地の取得
  • Google Maps API → 地図の表示と操作

この記事では、この2つを組み合わせて「現在地を取得してマップがスッと動く」仕組みを作っていきます。

まずは完成デモを通して全体の動きを確認し、その後でコードのポイントを解説していきます。
単に動くコードを紹介するだけでなく、「各処理の意図や仕組み」を理解できる構成です。

Googleマップについては、2025年現在のGoogle公式仕様に沿った最新の書き方(importLibrary()によるライブラリ読み込みや AdvancedMarkerElement の利用など)を採用しています。これから学ぶ方にも、安心して参考にできる内容です。

なお、今回のデモではGoogle Maps JavaScript APIを使うため、「地図をAPIで表示する方法」や「カスタマイズの基本」を知っておくと、より理解しやすくなります。まだ読んでいない方は、次の2つの記事もチェックしてみてください。

あわせて読みたい
【2025年版】GoogleマップをAPIで表示する方法|APIキーの取得から導入まで解説
【2025年版】GoogleマップをAPIで表示する方法|APIキーの取得から導入まで解説
あわせて読みたい
【2025年版】Google Maps JavaScript API カスタマイズ解説(マーカー・経路・配色)
【2025年版】Google Maps JavaScript API カスタマイズ解説(マーカー・経路・配色)

完成デモの紹介

まずは、今回作成するデモの完成形を見てみましょう。下のボタンを押すと、ブラウザが現在地を取得し、地図が自動的にその位置へ移動します。画面中央には、青いドットで現在地が表示されます。

「現在地へ移動」を押してください。

このデモでは、以下のような流れで処理が行われています。

  1. 地図の初期設定
    Google Maps JavaScript APIを使って地図を描画します(2025年現在の最新仕様である importLibrary() を使用)。
  2. ボタンクリックで現在地を取得
    JavaScriptのGeolocation APIを使って、ユーザーの緯度・経度を取得します。
  3. 取得した位置情報を地図に反映
    地図の中心を現在地に移動し、青いドット(カスタムマーカー)を表示します。

ボタンを押すと、ブラウザが「位置情報の利用を許可しますか?」というダイアログを表示します。ぜひ「許可」と「拒否」の両方を試してみてください。拒否した場合でも、デモ内のエラーメッセージがどのように表示されるかを確認できます。

また、これらの処理にあわせて、地図の下のステータス欄にメッセージを表示・更新しています。たとえば「現在地を取得しています…」「取得成功」「位置情報の利用が拒否されました」など、状況に応じて内容が切り替わる仕組みです。

コード全体(HTML / CSS / JavaScript)

ここからは、完成デモを構成しているコードを順に見ていきます。全体を通してシンプルな構成で、各パートには理解しやすいようコメントも付けています。まずはコードをざっと眺めて、動作の流れをつかんでみましょう。

HTMLコード

HTMLでは、地図の表示エリア・ステータス表示・「現在地へ移動」ボタンの3つを用意します。JavaScriptから操作するためのIDを適切に付けておくのがポイントです。

また、Googleマップを使うために、Google Maps JavaScript APIの読み込みスクリプトも記述します。このスクリプトで importLibrary() が使えるようになり、地図の描画やマーカー機能を利用できるようになります。APIキーを指定する部分だけ、ご自身のプロジェクトのものに置き換えてください。

APIキーの取得方法がまだの方は、【2025年版】GoogleマップをAPIで表示する方法で手順を確認しておくとスムーズです。

<!-- =========================
  現在地取得デモ:HTML構造
  (Googleマップ+現在地ボタン+ステータス表示)
========================= -->
<!-- 地図を表示するコンテナ -->
<div id="map" class="map"></div>

<!-- ステータス表示領域(メッセージをJavaScriptで更新) -->
<div class="status-wrapper">
  <p id="status" class="status">「現在地へ移動」を押してください。</p>
</div>

<!-- 現在地を取得して地図を移動させるボタン -->
<button id="btn" class="btn" type="button">現在地へ移動</button>

<!--
  Google Maps JavaScript API の読み込みスクリプト
  - key: Google Cloud で発行した API キーを指定してください
  - v: 利用するバージョン。特に理由がなければ "weekly" のままで大丈夫です
  この読み込みで、JavaScript 側から google.maps.importLibrary(...) が使えるようになります
-->
<script>
  (g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
    key: "YOUR_API_KEY",
    v: "weekly",
  });
</script>

CSSコード

CSSでは、地図のサイズ指定、現在地ドットのアニメーション、ボタンのスタイルなどを定義しています。特に .my-location-dot の部分では、波紋が広がるようなアニメーションを設定し、現在地を視覚的にわかりやすくしています。

/* =========================
  地図表示エリア
  - 幅は親要素に追従
  - 高さは固定(レスポンシブ対応)
========================= */
.map {
  height: 400px;
}

/* スマホ画面では高さを少し低く */
@media (max-width: 767px) {
  .map {
    height: 300px;
  }
}

/* =========================
  現在地ドット(AdvancedMarkerElement内のcontent)
  - 青い点+白い縁取りで視認性を確保
========================= */
.my-location-dot {
  position: relative;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #1a73e8; /* 青(Googleマップ風) */
  box-shadow: 0 0 0 3px #fff; /* 白い外枠で地図上でも見やすく */
}

/* ドットの外側に広がる波紋アニメーション */
.my-location-dot::after {
  content: "";
  display: block;
  position: absolute;
  inset: -6px; /* 外側へ6px広げる */
  border: 2px solid rgba(26, 115, 232, .35);
  border-radius: 50%;
  animation: pulse 1600ms ease-out infinite;
}

/* 波紋の拡大アニメーション */
@keyframes pulse {
  0% { transform: scale(0.8); opacity: .8; }
  70% { transform: scale(1.6); opacity: 0; }
  100% { transform: scale(1.6); opacity: 0; }
}

/* =========================
  ステータス表示
  - 成功・失敗を色分けで強調
========================= */
.status-wrapper {
  display: flex;
  justify-content: center;
  margin-top: 20px;
}

.status {
  font-size: 16px;
  line-height: 1.7;
  text-align: left;
}

@media (max-width: 767px) {
  .status {
    font-size: 15px;
  }
}

/* 強調テキスト(成功/失敗) */
.status strong {
  font-weight: 700;
}

.status strong.is-success {
  color: #15803d; /* 緑(成功メッセージ) */
}

.status strong.is-error {
  color: #b91c1c; /* 赤(エラーメッセージ) */
}

/* =========================
  「現在地へ移動」ボタン
  - 見た目と操作感のスタイル定義
========================= */
.btn {
  display: block;
  margin: 20px auto 0;
  padding: 15px 30px;
  border: none;
  border-radius: 5px;
  background: #c11a51;
  color: #fff;
  font: inherit;
  font-weight: 700;
  line-height: 1.4;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  appearance: none;
  transition: background-color 300ms;
}

@media (max-width: 767px) {
  .btn {
    padding: 15px 25px;
  }
}

@media (min-width: 768px) {
  .btn:hover {
    background: #890631;
  }
}

/* 無効状態(位置情報取得中) */
.btn:disabled {
  opacity: .5;
  cursor: not-allowed;
}

JavaScriptコード

JavaScriptでは、Geolocation APIで現在地を取得し、Google Maps JavaScript APIで地図の中心を移動&マーカーを表示しています。

importLibrary() を使った2025年現在の最新仕様に対応しており、AdvancedMarkerElement により、HTML要素を使った柔軟なマーカー表現を実現しています。

また、ユーザー操作や取得結果に応じてステータスメッセージを更新する仕組みも含まれており、「取得成功」「拒否」「タイムアウト」などの動きを一度に確認できます。

マップIDの取得方法がわからない方は、【2025年版】Google Maps JavaScript API カスタマイズ解説で手順を確認しておくとスムーズです。

/* =========================
  現在地を取得してマップ上に表示するデモ
  - importLibrary を使った最新のGoogle Maps API仕様対応
========================= */
(async () => {
  // Cloud Consoleで発行したMap ID
  const MAP_ID = "YOUR_MAP_ID";

  // 各要素の参照を取得
  const mapEl = document.getElementById("map");
  const statusEl = document.getElementById("status");
  const btnEl = document.getElementById("btn");

  try {
    // 必要なライブラリを読み込み(importLibraryは2025年現在の最新の書き方)
    const { Map } = await google.maps.importLibrary("maps");
    const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");

    /* =========================
      地図の初期設定
      - 東京駅を中心に地図を生成
      - 不要なUIは非表示にしてシンプルに
    ========================= */
    const map = new Map(mapEl, {
      zoom: 15,
      center: { lat: 35.681236, lng: 139.767125 },
      mapId: MAP_ID,
      zoomControl: true, // ズームボタン(+ / -)を表示
      cameraControl: false, // 新UI(上下左右のカメラ移動)を非表示
      mapTypeControl: false, // 地図 / 航空写真の切替を非表示
      scaleControl: false, // 縮尺バー(1kmスケールなど)を非表示
      streetViewControl: false, // ストリートビューアイコン(人型)を非表示
      clickableIcons: false // ランドマークや建物クリック時の吹き出しを無効化
    });

    // 現在地マーカーの参照用(初回以降の更新に使う)
    let userMarker = null; // AdvancedMarkerElement

    /* =========================
      「現在地へ移動」ボタンのクリック処理
    ========================= */
    btnEl.addEventListener("click", () => {
      // このブラウザが Geolocation API(位置情報を取得する機能)に対応しているかを確認
      // 対応していない場合は、この時点で処理を終了
      if (!("geolocation" in navigator)) {
        statusEl.textContent = "このブラウザは位置情報に対応していません。";
        return;
      }

      btnEl.disabled = true; // 二重クリック防止
      statusEl.textContent = "現在地を取得しています…";

      /* =========================
        位置情報の取得処理
        - 成功時:マップを現在地に移動+マーカー設置
        - 失敗時:エラー内容を表示
      ========================= */
      navigator.geolocation.getCurrentPosition(
        // 成功時
        (pos) => {
          const { latitude, longitude } = pos.coords;

          // 地図を現在地へ移動・ズーム
          map.panTo({ lat: latitude, lng: longitude });
          map.setZoom(15);

          // 一度押した後に再度ボタンを押した場合、前回のマーカーを消してから新しいマーカーを追加
          if (userMarker) userMarker.map = null;

          // 現在地ドットを作成して配置
          const dot = document.createElement("div");
          dot.className = "my-location-dot";

          // AdvancedMarkerElement: 地図上に表示するマーカーを作る機能。
          // HTMLで見た目を自由にカスタマイズできる。
          userMarker = new AdvancedMarkerElement({
            map, // 表示する対象の地図オブジェクト
            position: { lat: latitude, lng: longitude }, // マーカーを置く緯度経度(= 現在地)
            content: dot, // カスタムマーカーの中身(HTML要素)
            collisionBehavior: google.maps.CollisionBehavior.OPTIONAL_AND_HIDES_LOWER_PRIORITY,
            // 重なり時の表示優先度:他のラベル等よりこのマーカーを優先表示
          });

          // 緯度経度を小数点6桁で表示
          statusEl.innerHTML = `<strong class="is-success">取得成功:</strong>緯度 ${latitude.toFixed(6)}、経度 ${longitude.toFixed(6)}`;
          btnEl.disabled = false;
        },

        // 失敗時
        (err) => {
          let message = "";

          // エラーコードごとにメッセージを出し分け
          if (err.code === err.PERMISSION_DENIED) {
            message = "位置情報の利用が拒否されました。ブラウザの設定で許可してください。";
          } else if (err.code === err.POSITION_UNAVAILABLE) {
            message = "位置情報を取得できませんでした(信号なし/機内モードなど)。";
          } else if (err.code === err.TIMEOUT) {
            message = "タイムアウトしました。電波状況を確認して再試行してください。";
          } else {
            message = "不明なエラーが発生しました。";
          }

          // 取得失敗メッセージを表示
          statusEl.innerHTML = `<strong class="is-error">取得失敗:</strong>${message}`;
          btnEl.disabled = false;
        },

        // 取得オプション:できるだけ高精度で現在地を取得(最大10秒待ち、キャッシュは使わない)
        { enableHighAccuracy: true, timeout: 10000, maximumAge: 0 }
      );
    });

  } catch (e) {
    // Maps APIの読み込みエラーなど
    statusEl.textContent = "Googleマップの読み込みに失敗しました。";
  }
})();

コードのポイント解説

ここからは、先ほどのコードを構成する主なポイントを順に解説していきます。今回のデモは、位置情報の取得から地図への反映、そしてメッセージ更新までの流れで成り立っています。それぞれの処理の意図を理解することで、コード全体の仕組みがより明確になります。

ポイント1:Geolocation APIで現在地を取得

ユーザーの現在地を取得するには、ブラウザ標準のGeolocation APIを使います。今回のコードでは、次のように navigator.geolocation.getCurrentPosition() を呼び出しています。

navigator.geolocation.getCurrentPosition(success, error, {
  enableHighAccuracy: true,
  timeout: 10000,
  maximumAge: 0
});

この関数は、位置情報の取得が成功した場合は success 関数を、失敗した場合は error 関数を呼び出す仕組みになっています。

それぞれの関数には、次のような情報が渡されます。

  • success(pos):現在位置の情報が入ったオブジェクト。
    pos.coords.latitudepos.coords.longitude から緯度・経度を取得できます。
  • error(err):エラー内容が入ったオブジェクト。
    err.code をもとに、拒否・タイムアウトなどの原因を判定します。

オプションでは、次の3つを指定しています。

enableHighAccuracyより高精度な位置情報を取得する(GPSなどを優先的に利用)
timeout取得の制限時間(ミリ秒)。ここでは10秒を設定
maximumAgeキャッシュを使わず、常に最新の情報を取得(0で無効化)

また、初回の取得時にはブラウザが自動的に「このサイトがあなたの位置情報を使用することを許可しますか?」というダイアログを表示します。許可・拒否のどちらを選んでも、コード内の処理でそれぞれの結果をハンドリングできるようになっています。

このAPIを使うだけで、追加のライブラリを使わずに緯度・経度を取得できるのが大きな特徴です。位置情報機能を持つUIの基礎として、まずここをしっかり押さえておきましょう。

ポイント2:Google Maps APIの初期化とimportLibrary

地図の描画にはGoogle Maps JavaScript APIを使用しています。2025年現在では、従来の new google.maps.Map() ではなく、importLibrary() を使った新しいライブラリ読み込み構文が推奨されています。

const { Map } = await google.maps.importLibrary("maps");

この書き方により、必要なライブラリだけを動的に読み込めるため、パフォーマンス面でも効率的です。同様に、マーカー機能を利用するために以下も読み込んでいます。

const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");

次に、地図の初期化を行います。地図を生成する際は、HTML側で指定した <div id="map"> をターゲットとして新しい Map インスタンスを作成します。

const map = new Map(mapEl, {
  zoom: 15,
  center: { lat: 35.681236, lng: 139.767125 },
  mapId: MAP_ID,
  zoomControl: true, // ズームボタン(+ / -)を表示
  cameraControl: false, // 新UI(上下左右のカメラ移動)を非表示
  mapTypeControl: false, // 地図 / 航空写真の切替を非表示
  scaleControl: false, // 縮尺バー(1kmスケールなど)を非表示
  streetViewControl: false, // ストリートビューアイコン(人型)を非表示
  clickableIcons: false // ランドマークや建物クリック時の吹き出しを無効化
});

ここでは、東京駅を初期表示の中心に設定しています。また、ズームボタン以外のUIをすべてオフにして、シンプルで見やすい構成にしています。

mapId には、Google Cloud Consoleで発行したマップスタイルIDを指定します。これを設定すると、クラウド側で定義した配色やデザインが自動的に適用されます。地図の配色やマーカーのスタイルなどを詳しくカスタマイズしたい方は、以下の記事もあわせてチェックしてみてください。

あわせて読みたい
【2025年版】Google Maps JavaScript API カスタマイズ解説(マーカー・経路・配色)
【2025年版】Google Maps JavaScript API カスタマイズ解説(マーカー・経路・配色)

ポイント3:現在地ドットの追加(AdvancedMarkerElement)

取得した緯度・経度をもとに、地図上に現在地を示すドット(マーカー)を配置します。ここでは、Google Maps APIの新しい仕組みであるAdvancedMarkerElementを使っています。

const dot = document.createElement("div");
dot.className = "my-location-dot";

userMarker = new AdvancedMarkerElement({
  map, // 表示する対象の地図オブジェクト
  position: { lat: latitude, lng: longitude }, // マーカーを置く緯度経度(= 現在地)
  content: dot, // カスタムマーカーの中身(HTML要素)
  collisionBehavior: google.maps.CollisionBehavior.OPTIONAL_AND_HIDES_LOWER_PRIORITY,
  // 重なり時の表示優先度:他のラベル等よりこのマーカーを優先表示
});

AdvancedMarkerElement は、2023年以降に追加された新しいマーカー仕様で、従来の google.maps.Marker よりも柔軟にHTML要素を扱えるのが特徴です。content プロパティに任意のHTML要素を渡すことで、自由な見た目(今回はアニメーション付きの青いドット)を実現しています。

スワン
スワン

ドット自体は、クラス名を付けた <div> を1つ用意しているだけです。見た目やアニメーションはすべてCSS側で定義しています。

また、collisionBehavior はマーカーの重なり順序を制御するオプションです。ここでは OPTIONAL_AND_HIDES_LOWER_PRIORITY を指定し、地図上の他ラベルよりも現在地ドットを優先的に表示しています。

ポイント4:状態に応じたUIの制御とメッセージ更新

現在地の取得処理では、ユーザーの操作状態に合わせてUIを変化させるようにしています。状態の変化を目に見える形にすることで、処理の流れを確認しやすくしています。

まず、ボタンを押した直後には、処理中であることを示すメッセージを表示し、重複操作を防ぐためにボタンを一時的に無効化します。

btnEl.disabled = true; // 二重クリック防止
statusEl.textContent = "現在地を取得しています…";

位置情報の取得が成功した場合は、地図を移動させてから成功メッセージを表示し、ボタンを再び有効に戻します。

statusEl.innerHTML = `<strong class="is-success">取得成功:</strong>緯度 ${latitude.toFixed(6)}、経度 ${longitude.toFixed(6)}`;
btnEl.disabled = false;

一方、取得が失敗した場合は、エラー内容に応じてメッセージを切り替えています。拒否・タイムアウト・信号なしなど、err.code の値に応じてメッセージを分岐します。

if (err.code === err.PERMISSION_DENIED) {
  message = "位置情報の利用が拒否されました。ブラウザの設定で許可してください。";
} else if (err.code === err.POSITION_UNAVAILABLE) {
  message = "位置情報を取得できませんでした(信号なし/機内モードなど)。";
} else if (err.code === err.TIMEOUT) {
  message = "タイムアウトしました。電波状況を確認して再試行してください。";
} else {
  message = "不明なエラーが発生しました。";
}

// 取得失敗メッセージを表示
statusEl.innerHTML = `<strong class="is-error">取得失敗:</strong>${message}`;
btnEl.disabled = false;

今回は、状態ごとにメッセージやボタンを切り替える基本形を紹介しました。実務では、取得中にローディングを出したり、エラー時に再試行ボタンを出すなど、自分のUIに合った見せ方に発展させてみてください。

まとめ

JavaScriptのGeolocation APIを使えば、数行のコードで現在位置を取得できます。今回のように地図と組み合わせれば、実際のUIで位置情報を扱う感覚をつかめます。

まずは「取得→表示」の流れを理解し、そこから自分のサイトに合った使い方へ発展させてみてください。

押していただけると励みになります!

ABOUT ME
みなと
みなと
フロントエンドエンジニア
東京のWeb制作会社で15年以上働いている現役フロントエンドエンジニアです。これまで、いろんなプロジェクトに関わりながら、フロントエンド開発やWebデザインに取り組んできました。このブログでは、今までの経験を活かして、Web制作に役立つ情報やノウハウをシェアしていきたいと思います。初心者の方から、現場で働く方まで、誰でも参考にできる内容をお届けしますので、ぜひ覗いてみてください。
記事URLをコピーしました