Use Cases

Google Maps Web with Claude Code

Aprenda sobre google maps web usando o Claude Code. Dicas praticas e exemplos de codigo incluidos.

地図機能をClaude Codeで統合する

店舗検索、配達追跡、不動産検索など、地図機能を必要とするアプリケーションは数多くあります。Claude Codeを使えば、Google Maps APIやMapboxの統合、マーカー表示、ジオコーディングを効率的に実装できます。

Google Maps Reactコンポーネント

> Google Maps APIをReactアプリに統合して。
> 複数マーカー表示、情報ウィンドウ、現在地取得、
> 住所検索(ジオコーディング)を実装して。
// src/components/GoogleMap.tsx
'use client';
import { useRef, useEffect, useState, useCallback } from 'react';
import { Loader } from '@googlemaps/js-api-loader';

interface MapMarker {
  id: string;
  position: { lat: number; lng: number };
  title: string;
  description?: string;
}

interface Props {
  markers: MapMarker[];
  center?: { lat: number; lng: number };
  zoom?: number;
  onMarkerClick?: (marker: MapMarker) => void;
}

export function GoogleMap({
  markers,
  center = { lat: 35.6812, lng: 139.7671 }, // 東京駅
  zoom = 13,
  onMarkerClick,
}: Props) {
  const mapRef = useRef<HTMLDivElement>(null);
  const [map, setMap] = useState<google.maps.Map | null>(null);
  const [infoWindow, setInfoWindow] = useState<google.maps.InfoWindow | null>(null);

  useEffect(() => {
    const loader = new Loader({
      apiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_KEY!,
      version: 'weekly',
      libraries: ['places'],
    });

    loader.load().then(() => {
      if (!mapRef.current) return;
      const mapInstance = new google.maps.Map(mapRef.current, {
        center,
        zoom,
        styles: [
          { featureType: 'poi', stylers: [{ visibility: 'simplified' }] },
        ],
      });
      setMap(mapInstance);
      setInfoWindow(new google.maps.InfoWindow());
    });
  }, []);

  useEffect(() => {
    if (!map || !infoWindow) return;

    markers.forEach((markerData) => {
      const marker = new google.maps.Marker({
        position: markerData.position,
        map,
        title: markerData.title,
        animation: google.maps.Animation.DROP,
      });

      marker.addListener('click', () => {
        infoWindow.setContent(`
          <div style="padding:8px">
            <h3 style="font-weight:bold;margin-bottom:4px">${markerData.title}</h3>
            ${markerData.description ? `<p style="color:#666">${markerData.description}</p>` : ''}
          </div>
        `);
        infoWindow.open(map, marker);
        onMarkerClick?.(markerData);
      });
    });
  }, [map, markers, infoWindow, onMarkerClick]);

  return <div ref={mapRef} className="w-full h-96 rounded-xl" />;
}

住所検索(ジオコーディング)

// src/lib/geocoding.ts
export async function geocodeAddress(address: string) {
  const geocoder = new google.maps.Geocoder();

  const result = await geocoder.geocode({ address });

  if (result.results.length === 0) {
    throw new Error('住所が見つかりませんでした');
  }

  const location = result.results[0].geometry.location;
  return {
    lat: location.lat(),
    lng: location.lng(),
    formattedAddress: result.results[0].formatted_address,
  };
}

export async function reverseGeocode(lat: number, lng: number) {
  const geocoder = new google.maps.Geocoder();
  const result = await geocoder.geocode({
    location: { lat, lng },
  });

  return result.results[0]?.formatted_address || '住所不明';
}

店舗検索コンポーネント

// src/components/StoreLocator.tsx
'use client';
import { useState } from 'react';
import { GoogleMap } from './GoogleMap';
import { geocodeAddress } from '@/lib/geocoding';

interface Store {
  id: string;
  name: string;
  address: string;
  position: { lat: number; lng: number };
  phone: string;
  hours: string;
}

export function StoreLocator({ stores }: { stores: Store[] }) {
  const [searchQuery, setSearchQuery] = useState('');
  const [selectedStore, setSelectedStore] = useState<Store | null>(null);
  const [mapCenter, setMapCenter] = useState({ lat: 35.6812, lng: 139.7671 });

  const handleSearch = async () => {
    try {
      const result = await geocodeAddress(searchQuery);
      setMapCenter({ lat: result.lat, lng: result.lng });
    } catch {
      alert('住所が見つかりませんでした');
    }
  };

  const markers = stores.map((store) => ({
    id: store.id,
    position: store.position,
    title: store.name,
    description: store.address,
  }));

  return (
    <div className="grid md:grid-cols-3 gap-6">
      <div className="md:col-span-1 space-y-4">
        <div className="flex gap-2">
          <input
            value={searchQuery}
            onChange={(e) => setSearchQuery(e.target.value)}
            placeholder="住所・地名で検索"
            className="flex-1 border rounded-lg px-3 py-2"
            onKeyDown={(e) => e.key === 'Enter' && handleSearch()}
          />
          <button onClick={handleSearch} className="bg-blue-600 text-white px-4 rounded-lg">
            検索
          </button>
        </div>

        <div className="space-y-2 max-h-96 overflow-y-auto">
          {stores.map((store) => (
            <div
              key={store.id}
              onClick={() => {
                setSelectedStore(store);
                setMapCenter(store.position);
              }}
              className={`p-3 rounded-lg cursor-pointer border ${
                selectedStore?.id === store.id ? 'border-blue-500 bg-blue-50' : 'hover:bg-gray-50'
              }`}
            >
              <h4 className="font-medium">{store.name}</h4>
              <p className="text-sm text-gray-500">{store.address}</p>
              <p className="text-sm text-gray-400">{store.hours}</p>
            </div>
          ))}
        </div>
      </div>

      <div className="md:col-span-2">
        <GoogleMap
          markers={markers}
          center={mapCenter}
          zoom={14}
          onMarkerClick={(m) => setSelectedStore(stores.find((s) => s.id === m.id) || null)}
        />
      </div>
    </div>
  );
}

現在地の取得

// src/hooks/useGeolocation.ts
import { useState, useEffect } from 'react';

export function useGeolocation() {
  const [position, setPosition] = useState<{ lat: number; lng: number } | null>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (!navigator.geolocation) {
      setError('このブラウザでは位置情報が利用できません');
      return;
    }

    navigator.geolocation.getCurrentPosition(
      (pos) => setPosition({ lat: pos.coords.latitude, lng: pos.coords.longitude }),
      (err) => setError(err.message),
      { enableHighAccuracy: true, timeout: 10000 }
    );
  }, []);

  return { position, error };
}

関連記事

データ可視化との連携はデータ可視化の実装、APIキーの管理はセキュリティ監査も参考にしてください。

Google Maps Platform の公式ドキュメント(developers.google.com/maps)で最新のAPIリファレンスを確認できます。

#Claude Code #Google Maps #map #Mapbox #geolocation