# StaticMap Component for Astro ## Static Map Options | Provider | API Key | Features | Limitations | Example URL | |----------|---------|----------|-------------|------------| | Google Maps Static API | Required | Multiple marker styles, road/satellite/hybrid views | Limited free tier | `https://maps.googleapis.com/maps/api/staticmap?center=-2.2697,40.9025&zoom=14&size=600x400&markers=color:red%7C-2.2697,40.9025&key=YOUR_API_KEY` | | Mapbox Static Maps | Required | Highly customizable styles, multiple layers | Complex URL structure | `https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/pin-s+ff0000(-2.2697,40.9025)/-2.2697,40.9025,14,0/600x400?access_token=YOUR_API_KEY` | | OpenStreetMap Static | Not required | Free, simple implementation | Limited styling | `https://staticmap.openstreetmap.de/staticmap.php?center=-2.2697,40.9025&zoom=14&size=600x400&markers=-2.2697,40.9025,red` | | MapTiler | Required | Custom styles, vector tiles | Less common | `https://api.maptiler.com/maps/streets/static/40.9025,-2.2697,14/600x400.png?markers=40.9025,-2.2697,red&key=YOUR_API_KEY` | | HERE Maps | Required | Good international coverage | Less flexible styling | `https://image.maps.ls.hereapi.com/mia/1.6/mapview?c=-2.2697,40.9025&z=14&w=600&h=400&poi=-2.2697,40.9025&apiKey=YOUR_API_KEY` | ## Astro Component Here's a complete Astro component that supports all the providers mentioned above: ```astro --- // src/components/StaticMap.astro export interface GeoPos { lon: number; lat: number; } export interface Location { geo: GeoPos; title: string; } export interface Options { zoom?: number; width?: number; height?: number; apiKey?: string; provider?: 'google' | 'mapbox' | 'openstreetmap' | 'maptiler' | 'here'; mapType?: string; markerColor?: string; } const DEFAULT_LOCATION: Location = { geo: { lat: -2.2697, // Latitude for Lamu, Kenya lon: 40.9025 // Longitude for Lamu, Kenya }, title: "Lamu, Kenya" }; const DEFAULT_OPTIONS: Options = { zoom: 14, width: 600, height: 400, provider: 'google', mapType: 'roadmap', markerColor: 'red' }; interface Props { locations?: Location[]; options?: Options; } const { locations = [DEFAULT_LOCATION], options = {} } = Astro.props; const mergedOptions = { ...DEFAULT_OPTIONS, ...options }; const { zoom, width, height, apiKey, provider, mapType, markerColor } = mergedOptions; // Function to build URL based on provider function buildMapUrl(provider: string, locations: Location[], options: Options): string { const { zoom, width, height, apiKey, mapType, markerColor } = options; switch (provider) { case 'google': let googleUrl = 'https://maps.googleapis.com/maps/api/staticmap?'; // Center map on the first location if available if (locations.length > 0) { googleUrl += `center=${locations[0].geo.lat},${locations[0].geo.lon}&`; } // Add zoom, size and map type googleUrl += `zoom=${zoom}&size=${width}x${height}&maptype=${mapType}&`; // Add markers locations.forEach(location => { googleUrl += `markers=color:${markerColor}%7C${location.geo.lat},${location.geo.lon}&`; }); // Add API key if available if (apiKey) { googleUrl += `key=${apiKey}`; } return googleUrl; case 'mapbox': let mapboxUrl = 'https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/'; // Add markers if (locations.length > 0) { locations.forEach((location, index) => { if (index > 0) mapboxUrl += ','; const color = markerColor.startsWith('#') ? markerColor.substring(1) : markerColor; mapboxUrl += `pin-s+${color}(${location.geo.lon},${location.geo.lat})`; }); mapboxUrl += '/'; } // Add center coordinates, zoom and size const firstLocation = locations[0]; mapboxUrl += `${firstLocation.geo.lon},${firstLocation.geo.lat},${zoom},0/${width}x${height}`; // Add API key if (apiKey) { mapboxUrl += `?access_token=${apiKey}`; } return mapboxUrl; case 'openstreetmap': let osmUrl = 'https://staticmap.openstreetmap.de/staticmap.php?'; // Add center, zoom and size if (locations.length > 0) { osmUrl += `center=${locations[0].geo.lat},${locations[0].geo.lon}&zoom=${zoom}&size=${width}x${height}&`; } // Add markers locations.forEach(location => { osmUrl += `markers=${location.geo.lat},${location.geo.lon},${markerColor}&`; }); return osmUrl; case 'maptiler': let maptilerUrl = 'https://api.maptiler.com/maps/streets/static/'; // Add center coordinates, zoom and size const firstLocMaptiler = locations[0]; maptilerUrl += `${firstLocMaptiler.geo.lon},${firstLocMaptiler.geo.lat},${zoom}/${width}x${height}.png?`; // Add markers if (locations.length > 0) { locations.forEach((location, index) => { maptilerUrl += `markers=${location.geo.lon},${location.geo.lat},${markerColor}&`; }); } // Add API key if (apiKey) { maptilerUrl += `key=${apiKey}`; } return maptilerUrl; case 'here': let hereUrl = 'https://image.maps.ls.hereapi.com/mia/1.6/mapview?'; // Add center, zoom and size if (locations.length > 0) { hereUrl += `c=${locations[0].geo.lat},${locations[0].geo.lon}&z=${zoom}&w=${width}&h=${height}&`; } // Add markers locations.forEach((location, index) => { hereUrl += `poi=${location.geo.lat},${location.geo.lon}&`; }); // Add API key if (apiKey) { hereUrl += `apiKey=${apiKey}`; } return hereUrl; default: return ''; } } const mapUrl = buildMapUrl(provider!, locations, mergedOptions); ---