Intégration de cartes avec Claude Code
Découvrez intégration de cartes avec Claude Code. Conseils pratiques et exemples de code inclus.
地図機能を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リファレンスを確認できます。
Related Posts
Comment booster vos projets personnels avec Claude Code [Avec exemples]
Apprenez à accélérer considérablement vos projets de développement personnels avec Claude Code. Inclut des exemples concrets et un workflow pratique de l'idée au déploiement.
Comment automatiser le refactoring avec Claude Code
Apprenez à automatiser efficacement le refactoring de code avec Claude Code. Inclut des prompts pratiques et des patterns de refactoring concrets pour des projets réels.
Guide complet de configuration CORS avec Claude Code
Découvrez le guide complet de configuration CORS avec Claude Code. Conseils pratiques et exemples de code inclus.