Use Cases

API Usage Guide Geolocation API with Claude Code

Learn about api usage guide geolocation api using Claude Code. Practical tips and code examples included.

位置情報APIでロケーションベースの機能を実装

Geolocation APIを使えば、ユーザーの現在地を取得してローカル検索やナビゲーション機能を提供できます。Claude Codeを活用すると、権限管理やエラーハンドリングを含めた堅牢な実装を効率よく構築できます。

位置情報取得の基本

> ユーザーの現在位置を取得するReactフックを作成して。
> 権限管理、エラーハンドリング、ローディング状態を含めて。
// hooks/useGeolocation.ts
import { useState, useEffect, useCallback } from 'react';

interface GeolocationState {
  latitude: number | null;
  longitude: number | null;
  accuracy: number | null;
  loading: boolean;
  error: string | null;
  timestamp: number | null;
}

interface UseGeolocationOptions {
  enableHighAccuracy?: boolean;
  timeout?: number;
  maximumAge?: number;
}

export function useGeolocation(options: UseGeolocationOptions = {}) {
  const [state, setState] = useState<GeolocationState>({
    latitude: null,
    longitude: null,
    accuracy: null,
    loading: false,
    error: null,
    timestamp: null,
  });

  const getCurrentPosition = useCallback(() => {
    if (!navigator.geolocation) {
      setState(prev => ({ ...prev, error: 'Geolocation APIは非対応です' }));
      return;
    }

    setState(prev => ({ ...prev, loading: true, error: null }));

    navigator.geolocation.getCurrentPosition(
      (position) => {
        setState({
          latitude: position.coords.latitude,
          longitude: position.coords.longitude,
          accuracy: position.coords.accuracy,
          loading: false,
          error: null,
          timestamp: position.timestamp,
        });
      },
      (error) => {
        const messages: Record<number, string> = {
          1: '位置情報の取得が拒否されました',
          2: '位置情報を取得できませんでした',
          3: '位置情報の取得がタイムアウトしました',
        };
        setState(prev => ({
          ...prev,
          loading: false,
          error: messages[error.code] || '不明なエラー',
        }));
      },
      {
        enableHighAccuracy: options.enableHighAccuracy ?? false,
        timeout: options.timeout ?? 10000,
        maximumAge: options.maximumAge ?? 0,
      }
    );
  }, [options.enableHighAccuracy, options.timeout, options.maximumAge]);

  return { ...state, getCurrentPosition };
}

位置情報を活用したコンポーネント

// components/NearbySearch.tsx
import { useGeolocation } from '../hooks/useGeolocation';

export function NearbySearch() {
  const { latitude, longitude, loading, error, getCurrentPosition } = useGeolocation({
    enableHighAccuracy: true,
  });

  return (
    <div className="rounded-xl border p-6">
      <h2 className="mb-4 text-xl font-bold">近くのスポットを検索</h2>
      
      {!latitude && !loading && (
        <button
          onClick={getCurrentPosition}
          className="rounded-lg bg-blue-600 px-4 py-2 text-white hover:bg-blue-700"
        >
          現在地を取得
        </button>
      )}

      {loading && (
        <div className="flex items-center gap-2 text-gray-600">
          <span className="animate-spin">⏳</span>
          位置情報を取得中...
        </div>
      )}

      {error && (
        <div className="rounded-lg bg-red-50 p-3 text-red-600">{error}</div>
      )}

      {latitude && longitude && (
        <div>
          <p className="mb-2 text-sm text-gray-600">
            現在地: {latitude.toFixed(4)}, {longitude.toFixed(4)}
          </p>
          <NearbyResults lat={latitude} lng={longitude} />
        </div>
      )}
    </div>
  );
}

リアルタイム位置追跡

// hooks/useWatchPosition.ts
import { useState, useEffect, useRef } from 'react';

export function useWatchPosition() {
  const [positions, setPositions] = useState<GeolocationPosition[]>([]);
  const watchIdRef = useRef<number | null>(null);

  const startTracking = () => {
    if (!navigator.geolocation) return;

    watchIdRef.current = navigator.geolocation.watchPosition(
      (position) => {
        setPositions(prev => [...prev, position]);
      },
      (error) => console.error('追跡エラー:', error),
      { enableHighAccuracy: true, maximumAge: 5000 }
    );
  };

  const stopTracking = () => {
    if (watchIdRef.current !== null) {
      navigator.geolocation.clearWatch(watchIdRef.current);
      watchIdRef.current = null;
    }
  };

  useEffect(() => {
    return stopTracking;
  }, []);

  return { positions, startTracking, stopTracking };
}

距離計算ユーティリティ

// utils/geo.ts
export function haversineDistance(
  lat1: number, lon1: number,
  lat2: number, lon2: number
): number {
  const R = 6371; // 地球の半径(km)
  const dLat = toRad(lat2 - lat1);
  const dLon = toRad(lon2 - lon1);
  const a =
    Math.sin(dLat / 2) * Math.sin(dLat / 2) +
    Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
    Math.sin(dLon / 2) * Math.sin(dLon / 2);
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  return R * c;
}

function toRad(deg: number): number {
  return deg * (Math.PI / 180);
}

// Usage example
const distance = haversineDistance(35.6762, 139.6503, 34.6937, 135.5023);
console.log(`東京〜大阪: ${distance.toFixed(1)}km`); // 約396.9km

プライバシーへの配慮

// 位置情報の精度を意図的に下げる(プライバシー保護)
function coarsenLocation(lat: number, lng: number, precision: number = 2) {
  return {
    latitude: Number(lat.toFixed(precision)),
    longitude: Number(lng.toFixed(precision)),
  };
}

// サーバーに送信前にぼかす
async function sendLocation(lat: number, lng: number) {
  const coarse = coarsenLocation(lat, lng);
  await fetch('/api/location', {
    method: 'POST',
    body: JSON.stringify(coarse),
  });
}

Summary

Geolocation APIは、ローカル検索やナビゲーションなど多くのユースケースで活用できます。Claude Codeを使えば、セキュリティやプライバシーに配慮した実装を効率的に構築できます。レスポンシブデザインと組み合わせて、モバイルでの使い勝手も最適化しましょう。Geolocation APIの詳細仕様はMDN Web Docsを参照してください。

#Claude Code #Geolocation #geolocation #map #Web API