1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Google Maps JavaScript APIで「現在地追跡ボタン」を実装する方法

1
Last updated at Posted at 2026-04-18

はじめに

Google Maps JavaScript APIを利用して、以下の条件で 現在値をリアルタイム追跡(watchPosition) するボタンを実装したので、まとめる。

  • 「現在値取得」ボタンを押すと現在値の追跡を開始する
  • 再度押すと追跡を停止する
  • 現在値にマーカー+誤差の円(Circle)を表示する
  • ボタンのON/OFFをCSSで切り替える

スマホアプリのような「現在値追跡」をWEBで実現する。

完成イメージ

  • 「現在値取得」ボタンを押すと追跡開始
  • 現在地が動くと、マーカーと円が追従する
  • 「取得解除」で追跡停止する

GoogleMaps JavaSCript APIを利用して作成した地図の左下にボタンを表示する

実装

1.Google Maps JavaScript API

GoogleMapsAPIのcontrolsは、通常のHTMLとは別レイヤで管理されるため、UIボタンを地図の任意位置に配置。
今回は、LEFT_BOTTOMに「現在値取得」ボタンを追加している。

  • document.createElement("button") で DOM を生成

  • map.controls[ControlPosition] に push することで、Google Maps の UI に統合

  • Maps API のコントロールは通常の DOM と違い、地図の上に固定配置される

maps.js
const locationButton = document.createElement("button"); //ボタンを生成
locationButton.textContent = "現在地取得";
locationButton.classList.add("custom-map-control-button");
map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(locationButton);

2.Geolocation API(位置情報の取得)+状態管理

GeolocationAPIのwatchPosition()を使うことで、GPSの変化に応じてコールバックが実行され、リアルタイム追跡を実装
また、追跡の開始・停止を正しく制御するためには、watchIDとisTrackingの2つで状態を管理する。これにより、ボタンのON/OFFと位置追跡の同期がとれる。

  • getCurrentPosition()は単発で実行
  • watchPosition()は位置が変わるたびにコールバックされる
  • スマホアプリのような位置追跡がWEBで実現可能
  • isTrackingでボタンのON/OFFを制御
  • watchIDを保持しなければ、clearWatch()ができない
  • マーカ―と円は毎回更新するので、変数で保持して都度削除
maps.js
locationButton.addEventListener("click", () => { //取得ボタンをクリック
  if (!isTracking) {
    setCurrentLocationTracking(map);
    locationButton.textContent = "取得解除";
    locationButton.classList.remove("tracking-off");
    locationButton.classList.add("tracking-on");
    isTracking = true;
  } else {
    if (watchId !== null) {
      navigator.geolocation.clearWatch(watchId);
      watchId = null;
    }
    if (currentMarker) currentMarker.map = null;
    if (currentCircle) currentCircle.setMap(null);
      locationButton.textContent = "現在地取得";
      locationButton.classList.remove("tracking-on");
      locationButton.classList.add("tracking-off");
      isTracking = false;
    }
  });
//~略
watchId = navigator.geolocation.watchPosition(
  (position) => {
    const pos = {
      lat: position.coords.latitude,
      lng: position.coords.longitude,
    };

  // 既存のマーカーと円を削除
  if (currentMarker) currentMarker.map = null;
  if (currentCircle) currentCircle.setMap(null);

  // 新しい円
  currentCircle = new google.maps.Circle({
    strokeColor: '#115EC3',
    strokeOpacity: 0.2,
    strokeWeight: 1,
    fillColor: '#115EC3',
    fillOpacity: 0.2,
    map: map,
    center: pos,
    radius: 50
  });
);

3.地図の追従

現在値が更新される度に、map.panTo()を呼び出すことで、地図が常にユーザーの位置を中心に表示する「追従モード」を実現

maps.js
const pos = {
            lat: position.coords.latitude,
            lng: position.coords.longitude,
          };
          //略
map.panTo(pos);

実装コード

maps.js
locationButton.classList.add("tracking-off"); // 初期状態

    locationButton.addEventListener("click", () => {
      if (!isTracking) {
        setCurrentLocationTracking(map);
        locationButton.textContent = "取得解除";
        locationButton.classList.remove("tracking-off");
        locationButton.classList.add("tracking-on");
        isTracking = true;
      } else {
        if (watchId !== null) {
          navigator.geolocation.clearWatch(watchId);
          watchId = null;
        }
        if (currentMarker) currentMarker.map = null;
        if (currentCircle) currentCircle.setMap(null);
        locationButton.textContent = "現在地取得";
        locationButton.classList.remove("tracking-on");
        locationButton.classList.add("tracking-off");
        isTracking = false;
      }
    });

    let currentMarker = null;
    let currentCircle = null;
    let watchId = null;

    function setCurrentLocationTracking(map) {
      if (!navigator.geolocation) return;

      // すでに追跡中なら止める
      if (watchId !== null) {
        navigator.geolocation.clearWatch(watchId);
      }

      let isFollowing = true;

      watchId = navigator.geolocation.watchPosition(
        (position) => {
          const pos = {
            lat: position.coords.latitude,
            lng: position.coords.longitude,
          };

          // 既存のマーカーと円を削除
          if (currentMarker) currentMarker.map = null;
          if (currentCircle) currentCircle.setMap(null);

          // 新しい円
          currentCircle = new google.maps.Circle({
            strokeColor: '#115EC3',
            strokeOpacity: 0.2,
            strokeWeight: 1,
            fillColor: '#115EC3',
            fillOpacity: 0.2,
            map: map,
            center: pos,
            radius: 50
          });

          // 新しいマーカー
          const iconElement = document.createElement('div');
          iconElement.style.width = '14px';
          iconElement.style.height = '14px';
          iconElement.style.backgroundColor = '#115EC3';
          iconElement.style.border = '2px solid white';
          iconElement.style.borderRadius = '50%';
          iconElement.style.boxSizing = 'border-box';

          currentMarker = new google.maps.marker.AdvancedMarkerElement({
            position: pos,
            map: map,
            content: iconElement
          });

          if(isFollowing) {
            map.panTo(pos);
          }
        },
        (error) => {
          console.error("位置情報の取得に失敗しました:", error);
        },
        {
          enableHighAccuracy: true,
          maximumAge: 0,
          timeout: 10000
        }
      );

      // 地図操作で追尾を止める
      map.addListener('dragstart', () => {
        isFollowing = false;
      });
    }

まとめ

  • Google Maps JavaSCript API+Geolocation APIで現在地追跡が実装できる
  • マーカーと円で現在地を視覚的に表示可能
  • スマホのようなUXをWEbでも実現可能

本機能はGASアプリに実装しましたが、視覚的にも正確に動きました。手探り状態で行っていましたが、成功したので備忘録も兼ねて残します。
今後、精度をより上げたり、UI向上を課題として取り組みたいと思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?