@jetblack/map
A map component for React.
The component has a few unique features:
- Is is built as a pure react component with no dependencies,
- When zoomed out the map can scroll continuously in the horizontal direction.
- It uses hooks to provide interaction with the map.
Demo
You can see a demo of the map here.
Installation
Install from npmjs:
npm install --save @jetblack/map
React is a peer dependency and will not be automatically installed.
Packages
There are two official packages:
- @jetblack/map-geojson - support for geojson
- @jetblack/map-cluster-marker - cluster markers
Usage
Basic
Here is a basic map using the default tile provider.
import { Map } from '@jetblack/map'
export default function App() {
return (
<Map width='600px' height='400px' />
)
}
Typically we will want to specify the center of the map and the zoom level.
import { Map } from '@jetblack/map'
const GREENWICH_OBSERVATORY: Coordinate = {
latitude: 51.47684676353231,
longitude: -0.0005261695762532147,
}
export default function App() {
return (
<Map
width='600px'
height='400px'
center={GREENWICH_OBSERVATORY}
zoom={12}
/>
)
}
Overlay Layer
An overlay layer can be added.
import {
Map,
Marker,
OverlayLayer,
SVGPin
} from '@jetblack/map'
const GREENWICH_OBSERVATORY: Coordinate = {
latitude: 51.47684676353231,
longitude: -0.0005261695762532147,
}
const BUCKINGHAM_PALACE: Coordinate = {
latitude: 51.501200111998415,
longitude: -0.14182556179982908,
}
export default function App() {
return (
<Map
width='600px'
height='400px'
center={GREENWICH_OBSERVATORY}
zoom={11}
>
<OverlayLayer>
<Marker
coordinate={GREENWICH_OBSERVATORY}
render={point => <SVGPin point={point} />}
/>
<Marker
coordinate={BUCKINGHAM_PALACE}
render={point => <SVGPin point={point} />}
/>
</OverlayLayer>
</Map>
)
}
Interaction
Hooks are provided for interaction with the map.
The default tile provider is Open Street Map (osmTileProvider
), which has a
tile width and height of 256.
import { useRef } from 'react'
import {
Coordinate,
Map,
Marker,
OverlayLayer,
Point,
SVGPin,
useClick,
useDrag,
useZoom,
} from '@jetblack/map'
const GREENWICH_OBSERVATORY: Coordinate = {
latitude: 51.47684676353231,
longitude: -0.0005261695762532147,
}
const EMPIRE_STATE_BUILDING: Coordinate = {
latitude: 40.748585815569854,
longitude: -73.9856543574467,
}
const tileSize = { width: 256, height: 256 }
export default function App() {
const ref = useRef<HTMLDivElement>(null)
const [zoom, setZoom] = useZoom({ ref, defaultZoom: 6 })
const [center, setCenter] = useDrag({
ref,
defaultCenter: GREENWICH_OBSERVATORY,
zoom,
tileSize
})
useClick({
ref,
center,
zoom,
tileSize,
onClick: (coordinate: Coordinate, point: Point) => {
console.log('click', { coordinate, point })
},
onDoubleClick: (coordinate: Coordinate, point: Point) => {
// Center and zoom to the double clicked point.
setCenter(coordinate)
setZoom(zoom + 1)
}
})
return (
<div style={{ textAlign: 'center', marginTop: 50 }}>
<div style={{ margin: '0 auto' }}>
<Map center={center} zoom={zoom} width="1000px" height="600px" ref={ref}>
<OverlayLayer>
<Marker
coordinate={GREENWICH_OBSERVATORY}
render={point => <SVGPin point={point} />}
/>
<Marker
coordinate={EMPIRE_STATE_BUILDING}
render={point => <SVGPin point={point} />}
/>
</OverlayLayer>
</Map>
</div>
</div>
)
}
Hooks
As shown in the example above some hooks are provided for interacting with the map.
The hooks are intentionally primitive. There are a number of excellent packages which can achieve this.
Acknowledgements
This is largely a reworking of other libraries.
In particular much of the heavy lifting was done by Pigeon Maps.
Another library which was a good source of ideas was react-slippy-map.