An open API service indexing awesome lists of open source software.

https://github.com/1amageek/mapkit

A React wrapper for Apple's MapKit JS, providing a seamless way to integrate Apple Maps into your React applications.
https://github.com/1amageek/mapkit

applemaps mapkit mapkit-js

Last synced: 12 months ago
JSON representation

A React wrapper for Apple's MapKit JS, providing a seamless way to integrate Apple Maps into your React applications.

Awesome Lists containing this project

README

          

# @1amageek/mapkit

A React wrapper for Apple's MapKit JS, providing a seamless way to integrate Apple Maps into your React applications.

## Features

- πŸ—ΊοΈ Full TypeScript support
- πŸ”„ React component lifecycle integration
- πŸ“ Support for markers, custom annotations, and overlays
- 🎨 Customizable map styling and controls
- πŸ”’ Automatic token management and refresh
- 🎯 Built-in error handling
- πŸ’« Smooth animations and transitions
- πŸ–±οΈ Comprehensive event handling for map interactions, annotations, and user location

## Installation

```bash
npm install @1amageek/mapkit
```

## Prerequisites

You'll need:
1. An Apple Developer account
2. A Maps ID from the Apple Developer portal
3. A token generation endpoint in your backend

## Basic Usage

First, wrap your application with the `MapKitProvider`:

```tsx
import { MapKitProvider } from '@1amageek/mapkit';

const App = () => {
const fetchToken = async () => {
// Fetch your MapKit JS token from your server
const response = await fetch('your-token-endpoint');
const data = await response.json();
return {
token: data.token,
expiresAt: data.expiresAt // Unix timestamp in seconds
};
};

return (



);
};
```

Then use the Map component:

```tsx
import { Map, MarkerAnnotation } from '@1amageek/mapkit';
```

## Event Handling

The library supports a wide range of events for the map, annotations, and user location:

### Map Events
The `Map` component emits various events related to map display and interaction:
- `onRegionChangeStart`: Triggered when the map region starts changing.
- `onRegionChangeEnd`: Triggered when the map region finishes changing.
- `onRotationStart`: Triggered when the map starts rotating.
- `onRotationEnd`: Triggered when the map finishes rotating.
- `onScrollStart`: Triggered when the map starts scrolling.
- `onScrollEnd`: Triggered when the map finishes scrolling.
- `onZoomStart`: Triggered when the map starts zooming.
- `onZoomEnd`: Triggered when the map finishes zooming.
- `onMapTypeChange`: Triggered when the map type changes (e.g., from satellite to standard).
- `onSingleTap`: Triggered when the map is tapped once.
- `onDoubleTap`: Triggered when the map is double-tapped.
- `onLongPress`: Triggered when the map is long-pressed.

### Annotation Events

- `onSelect`: Triggered when an annotation is selected
- `onDeselect`: Triggered when an annotation is deselected
- `onDrag`: Triggered while an annotation is being dragged, providing real-time updates.
- `onDragStart`: Triggered when starting to drag an annotation
- `onDragEnd`: Triggered when finishing dragging an annotation

### User Location Events
- `onUserLocationChange`: Triggered when the user's location changes. Provides the new coordinate and timestamp.
- `onUserLocationError`: Triggered when an error occurs while trying to retrieve the user's location.

Example usage with events:

```tsx
import { Map, MarkerAnnotation } from '@1amageek/mapkit';

const MapComponent = () => {

return (
) => {
console.log("Region change start", event);
}}
onRegionChangeEnd={(event: mapkit.EventBase) => {
console.log("Region change end", event);
}}
region={{
center: {
latitude: 35.6812,
longitude: 139.7671
},
span: {
latitudeDelta: 0.1,
longitudeDelta: 0.1
}
}}
>


);
};
```

## Event Types

```typescript
interface AnnotationEventHandlers {
onSelect?: (event: mapkit.EventBase) => void;
onDeselect?: (event: mapkit.EventBase) => void;
onDrag?: (event: mapkit.EventBase) => void;
onDragStart?: (event: mapkit.EventBase) => void;
onDragEnd?: (event: mapkit.EventBase) => void;
}
```

## Usage Examples

### Basic Marker Annotation with Events

```tsx

{
// Event when user clicks/taps the annotation
const annotation = event.target;
console.log('Selected:', annotation.title);
console.log('At coordinate:', annotation.coordinate);
}}
onDrag={(event) => {
// Real-time coordinate updates during drag
console.log('Current position:', event.coordinate);
}}
onDragEnd={(event) => {
// Final location after drag ends
const { latitude, longitude } = event.coordinate;
console.log('Final position:', { latitude, longitude });
}}
/>

```

### Custom Annotation with Complex Interaction

```tsx

{
// Access to DOM event and screen coordinates
console.log('Click position:', event.pointOnPage);
console.log('DOM event:', event.domEvent);
}}
callout={{
calloutContentForAnnotation: (annotation) => (


{annotation.title}


handleCalloutAction(annotation)}>
Details


)
}}
>

{/* Your custom marker content */}

```

### Multiple Annotations with Shared Event Handler

```tsx
const MapWithAnnotations = () => {
const handleAnnotationSelect = (event: mapkit.EventBase) => {
// Common handler for all annotations
const { title, data } = event.target;
console.log('Selected location:', title);
console.log('Custom data:', data);
};

return (

{locations.map((location) => (

))}

);
};
```

### Image Annotation with Clustering

```tsx

{
if (event.target.memberAnnotations) {
// This is a cluster
console.log('Cluster size:', event.target.memberAnnotations.length);
} else {
// Single annotation
console.log('Selected image annotation');
}
}}
/>

```

These event handlers are available for all annotation types (`MarkerAnnotation`, `ImageAnnotation`, `CustomAnnotation`).

# Advanced Features

### Custom Annotations

Create custom annotations with your own React components:

```tsx
import { CustomAnnotation } from '@1amageek/mapkit';

const CustomPin = () => (


Custom Pin


);
```

### Overlays

Add various types of overlays to your map:

```tsx
import { CircleOverlay, PolylineOverlay, PolygonOverlay } from '@1amageek/mapkit';

const MapWithOverlays = () => (




);
```

### Error Handling

The library provides built-in error handling:

```tsx
const MapComponent = () => (
{
console.error('Map error:', error);
}}
errorComponent={

Failed to load map
}
loadingComponent={
Loading map...
}
/>
);
```

## API Reference

### MapKitProvider Props

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| fetchToken | () => Promise | Yes | Function to fetch MapKit JS token |
| options | MapKitInitOptions | No | Initialization options |
| onError | (error: MapKitError) => void | No | Error handler |

### Map Props

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| id | string | No | Map container ID |
| options | mapkit.MapConstructorOptions | No | Map configuration options |
| location | Coordinate | No | Center Coordinate |
| region | Region | No | Map region with center and span |
| onMapError | (error: Error \| MapKitError) => void | No | Error handler |
| onAppear | (map: mapkit.Map) => void | No | Called when map is ready |
| onChange | (map: mapkit.Map, newAnnotations: mapkit.Annotation[]) => void | No | Called when annotations/overlays change |
| className | string | No | Additional CSS classes |
| loadingComponent | ReactNode | No | Custom loading component |
| errorComponent | ReactNode | No | Custom error component |
| onRegionChangeStart | (event: mapkit.EventBase) => void | No | Triggered when the map region starts changing. |
| onRegionChangeEnd | (event: mapkit.EventBase) => void | No | Triggered when the map region finishes changing. |
| onRotationStart | (event: mapkit.EventBase) => void | No | Triggered when the map starts rotating. |
| onRotationEnd | (event: mapkit.EventBase) => void | No | Triggered when the map finishes rotating. |
| onScrollStart | (event: mapkit.EventBase) => void | No | Triggered when the map starts scrolling. |
| onScrollEnd | (event: mapkit.EventBase) => void | No | Triggered when the map finishes scrolling. |
| onZoomStart | (event: mapkit.EventBase) => void | No | Triggered when the map starts zooming. |
| onZoomEnd | (event: mapkit.EventBase) => void | No | Triggered when the map finishes zooming. |
| onMapTypeChange | (event: mapkit.EventBase) => void | No | Triggered when the map type changes. |
| onUserLocationChange | (event: mapkit.EventBase & { coordinate: mapkit.Coordinate; timestamp: Date }) => void | No | Triggered when the user's location changes. |
| onUserLocationError | (event: mapkit.EventBase & { code: number; message: string }) => void | No | Triggered when an error occurs while trying to retrieve the user's location. |
| onSingleTap | (event: mapkit.EventBase) => void | No | Triggered when the map is tapped once. |
| onDoubleTap | (event: mapkit.EventBase) => void | No | Triggered when the map is double-tapped. |
| onLongPress | (event: mapkit.EventBase) => void | No | Triggered when the map is long-pressed. |

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## License

This project is licensed under the MIT License - see the LICENSE file for details.