1 | # Urbica React Mapbox GL JS
|
2 |
|
3 | [![Node CI](https://github.com/urbica/react-map-gl/workflows/Node%20CI/badge.svg)](https://github.com/urbica/react-map-gl/actions)
|
4 | [![codecov](https://codecov.io/gh/urbica/react-map-gl/branch/master/graph/badge.svg)](https://codecov.io/gh/urbica/react-map-gl)
|
5 | [![npm](https://img.shields.io/npm/dt/@urbica/react-map-gl.svg?style=popout)](https://www.npmjs.com/package/@urbica/react-map-gl)
|
6 | [![npm](https://img.shields.io/npm/v/@urbica/react-map-gl.svg?style=popout)](https://www.npmjs.com/package/@urbica/react-map-gl)
|
7 | ![npm bundle size (scoped)](https://img.shields.io/bundlephobia/minzip/@urbica/react-map-gl.svg)
|
8 |
|
9 | React Component Library for [Mapbox GL JS](https://github.com/mapbox/mapbox-gl-js). Mapbox GL JS is a JavaScript library that renders interactive maps from vector tiles and Mapbox styles using WebGL. This project is intended to be as close as possible to the [Mapbox GL JS API](https://docs.mapbox.com/mapbox-gl-js/api/).
|
10 |
|
11 | This project is heavily inspired by [uber/react-map-gl](https://github.com/uber/react-map-gl).
|
12 |
|
13 | - [Installation](#installation)
|
14 | - [Components](#components)
|
15 | - [Usage](#usage)
|
16 | - [Static Map](#static-map)
|
17 | - [Interactive Map](#interactive-map)
|
18 | - [MapGL with Source and Layer](#mapgl-with-source-and-layer)
|
19 | - [MapGL with GeoJSON Source](#mapgl-with-geojson-source)
|
20 | - [Custom Layers support](#custom-layers-support)
|
21 | - [Documentation](#documentation)
|
22 | - [Changelog](#changelog)
|
23 | - [License](#license)
|
24 | - [Contributing](#contributing)
|
25 | - [Team](#team)
|
26 |
|
27 | ![Gallery](https://raw.githubusercontent.com/urbica/react-map-gl/master/docs/gallery.jpg)
|
28 |
|
29 | ## Installation
|
30 |
|
31 | ```shell
|
32 | npm install --save mapbox-gl @urbica/react-map-gl
|
33 | ```
|
34 |
|
35 | ...or if you are using yarn:
|
36 |
|
37 | ```shell
|
38 | yarn add mapbox-gl @urbica/react-map-gl
|
39 | ```
|
40 |
|
41 | ### Optional Dependencies
|
42 |
|
43 | If you want to use the `LanguageControl`:
|
44 |
|
45 | ```shell
|
46 | npm install --save @mapbox/mapbox-gl-language
|
47 | ```
|
48 |
|
49 | ...or if you are using yarn:
|
50 |
|
51 | ```shell
|
52 | yarn add @mapbox/mapbox-gl-language
|
53 | ```
|
54 |
|
55 | ## Components
|
56 |
|
57 | | Component | Description |
|
58 | | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
59 | | [MapGL](src/components/MapGL) | Represents map on the page |
|
60 | | [MapContext](src/components/MapContext) | React Context API for the map instance |
|
61 | | [Source](src/components/Source) | [Sources](https://docs.mapbox.com/mapbox-gl-js/api/#sources) specify the geographic features to be rendered on the map |
|
62 | | [Layer](src/components/Layer) | [Layers](https://docs.mapbox.com/mapbox-gl-js/style-spec/#layers) specify the `Sources` style |
|
63 | | [Filter](src/components/Filter) | Set filter to existing layer |
|
64 | | [CustomLayer](src/components/CustomLayer) | Allow a user to render directly into the map's GL context |
|
65 | | [Image](src/components/Image) | Adds an image to the map style |
|
66 | | [Popup](src/components/Popup) | React Component for [Mapbox GL JS Popup](https://docs.mapbox.com/mapbox-gl-js/api/#popup) |
|
67 | | [Marker](src/components/Marker) | React Component for [Mapbox GL JS Marker](https://docs.mapbox.com/mapbox-gl-js/api/#marker) |
|
68 | | [FeatureState](src/components/FeatureState) | Sets the state of a geographic feature rendered on the map |
|
69 | | [AttributionControl](src/components/AttributionControl) | Represents the map's attribution information |
|
70 | | [LanguageControl](src/components/LanguageControl) | Adds support for switching the language of the map style |
|
71 | | [FullscreenControl](src/components/FullscreenControl) | Contains a button for toggling the map in and out of fullscreen mode |
|
72 | | [GeolocateControl](src/components/GeolocateControl) | Geolocate the user and then track their current location on the map |
|
73 | | [NavigationControl](src/components/NavigationControl) | Contains zoom buttons and a compass |
|
74 | | [ScaleControl](src/components/ScaleControl) | Displays the ratio of a distance on the map to the corresponding distance on the ground |
|
75 | | [Cluster](https://github.com/urbica/react-map-gl-cluster) | Cluster [Markers](src/components/Marker) with [supercluster](https://github.com/mapbox/supercluster) |
|
76 | | [Draw](https://github.com/urbica/react-map-gl-draw) | Support for drawing and editing features |
|
77 |
|
78 | ## Usage
|
79 |
|
80 | To use any of Mapbox’s tools, APIs, or SDKs, you’ll need a Mapbox [access token](https://www.mapbox.com/help/define-access-token/). Mapbox uses access tokens to associate requests to API resources with your account. You can find all your access tokens, create new ones, or delete existing ones on your [API access tokens page](https://www.mapbox.com/studio/account/tokens/).
|
81 |
|
82 | See [**Documentation**](https://urbica.github.io/react-map-gl/) for more examples.
|
83 |
|
84 | ### Static Map
|
85 |
|
86 | By default, `MapGL` component renders in a static mode. That means that the user cannot interact with the map.
|
87 |
|
88 | ```jsx
|
89 | import React from 'react';
|
90 | import MapGL from '@urbica/react-map-gl';
|
91 | import 'mapbox-gl/dist/mapbox-gl.css';
|
92 |
|
93 | <MapGL
|
94 | style={{ width: '100%', height: '400px' }}
|
95 | mapStyle="mapbox://styles/mapbox/light-v9"
|
96 | accessToken={MAPBOX_ACCESS_TOKEN}
|
97 | latitude={37.78}
|
98 | longitude={-122.41}
|
99 | zoom={11}
|
100 | />;
|
101 | ```
|
102 |
|
103 | ### Interactive Map
|
104 |
|
105 | In most cases, you will want the user to interact with the map. To do this, you need to provide `onViewportChange` handler, that will update map viewport state.
|
106 |
|
107 | ```jsx
|
108 | import React from 'react';
|
109 | import MapGL from '@urbica/react-map-gl';
|
110 | import 'mapbox-gl/dist/mapbox-gl.css';
|
111 |
|
112 | initialState = {
|
113 | viewport: {
|
114 | latitude: 37.78,
|
115 | longitude: -122.41,
|
116 | zoom: 11
|
117 | }
|
118 | };
|
119 |
|
120 | <MapGL
|
121 | style={{ width: '100%', height: '400px' }}
|
122 | mapStyle="mapbox://styles/mapbox/light-v9"
|
123 | accessToken={MAPBOX_ACCESS_TOKEN}
|
124 | latitude={state.viewport.latitude}
|
125 | longitude={state.viewport.longitude}
|
126 | zoom={state.viewport.zoom}
|
127 | onViewportChange={(viewport) => setState({ viewport })}
|
128 | />;
|
129 | ```
|
130 |
|
131 | ### MapGL with Source and Layer
|
132 |
|
133 | [Sources](https://docs.mapbox.com/mapbox-gl-js/api/#sources) specify the geographic features to be rendered on the map.
|
134 |
|
135 | [Layers](https://docs.mapbox.com/mapbox-gl-js/style-spec/#layers) specify the Sources styles. The type of layer is specified by the `"type"` property, and must be one of `background`, `fill`, `line`, `symbol`, `raster`, `circle`, `fill-extrusion`, `heatmap`, `hillshade`.
|
136 |
|
137 | Except for layers of the `background` type, each layer needs to refer to a source. Layers take the data that they get from a source, optionally filter features, and then define how those features are styled.
|
138 |
|
139 | ```jsx
|
140 | import React from 'react';
|
141 | import MapGL, { Source, Layer } from '@urbica/react-map-gl';
|
142 | import 'mapbox-gl/dist/mapbox-gl.css';
|
143 |
|
144 | <MapGL
|
145 | style={{ width: '100%', height: '400px' }}
|
146 | mapStyle="mapbox://styles/mapbox/light-v9"
|
147 | accessToken={MAPBOX_ACCESS_TOKEN}
|
148 | >
|
149 | <Source id="contours" type="vector" url="mapbox://mapbox.mapbox-terrain-v2" />
|
150 | <Layer
|
151 | id="contours"
|
152 | type="line"
|
153 | source="contours"
|
154 | source-layer="contour"
|
155 | paint={{
|
156 | 'line-color': '#877b59',
|
157 | 'line-width': 1
|
158 | }}
|
159 | />
|
160 | </MapGL>;
|
161 | ```
|
162 |
|
163 | ### MapGL with GeoJSON Source
|
164 |
|
165 | To draw a GeoJSON on a map, add `Source` with the `type` property set to `geojson` and `data` property set to a URL or inline [GeoJSON](http://geojson.org/).
|
166 |
|
167 | ```jsx
|
168 | import React from 'react';
|
169 | import MapGL, { Source, Layer } from '@urbica/react-map-gl';
|
170 | import 'mapbox-gl/dist/mapbox-gl.css';
|
171 |
|
172 | initialState = {
|
173 | viewport: {
|
174 | latitude: 37.830348,
|
175 | longitude: -122.486052,
|
176 | zoom: 15
|
177 | }
|
178 | };
|
179 |
|
180 | const data = {
|
181 | type: 'Feature',
|
182 | geometry: {
|
183 | type: 'LineString',
|
184 | coordinates: [
|
185 | [-122.48369693756104, 37.83381888486939],
|
186 | [-122.48348236083984, 37.83317489144141],
|
187 | [-122.48339653015138, 37.83270036637107],
|
188 | [-122.48356819152832, 37.832056363179625],
|
189 | [-122.48404026031496, 37.83114119107971],
|
190 | [-122.48404026031496, 37.83049717427869],
|
191 | [-122.48348236083984, 37.829920943955045],
|
192 | [-122.48356819152832, 37.82954808664175],
|
193 | [-122.48507022857666, 37.82944639795659],
|
194 | [-122.48610019683838, 37.82880236636284],
|
195 | [-122.48695850372314, 37.82931081282506],
|
196 | [-122.48700141906738, 37.83080223556934],
|
197 | [-122.48751640319824, 37.83168351665737],
|
198 | [-122.48803138732912, 37.832158048267786],
|
199 | [-122.48888969421387, 37.83297152392784],
|
200 | [-122.48987674713133, 37.83263257682617],
|
201 | [-122.49043464660643, 37.832937629287755],
|
202 | [-122.49125003814696, 37.832429207817725],
|
203 | [-122.49163627624512, 37.832564787218985],
|
204 | [-122.49223709106445, 37.83337825839438],
|
205 | [-122.49378204345702, 37.83368330777276]
|
206 | ]
|
207 | }
|
208 | };
|
209 |
|
210 | <MapGL
|
211 | style={{ width: '100%', height: '400px' }}
|
212 | mapStyle="mapbox://styles/mapbox/light-v9"
|
213 | accessToken={MAPBOX_ACCESS_TOKEN}
|
214 | onViewportChange={(viewport) => setState({ viewport })}
|
215 | {...state.viewport}
|
216 | >
|
217 | <Source id="route" type="geojson" data={data} />
|
218 | <Layer
|
219 | id="route"
|
220 | type="line"
|
221 | source="route"
|
222 | layout={{
|
223 | 'line-join': 'round',
|
224 | 'line-cap': 'round'
|
225 | }}
|
226 | paint={{
|
227 | 'line-color': '#888',
|
228 | 'line-width': 8
|
229 | }}
|
230 | />
|
231 | </MapGL>;
|
232 | ```
|
233 |
|
234 | ### Custom Layers support
|
235 |
|
236 | [Custom layers](https://docs.mapbox.com/mapbox-gl-js/api/#customlayerinterface) allow a user to render directly into the map's GL context using the map's camera.
|
237 |
|
238 | Here is an Uber [deck.gl](https://github.com/uber/deck.gl) usage example.
|
239 |
|
240 | ```jsx
|
241 | import React from 'react';
|
242 | import MapGL, { CustomLayer } from '@urbica/react-map-gl';
|
243 | import { MapboxLayer } from '@deck.gl/mapbox';
|
244 | import { ScatterplotLayer } from '@deck.gl/layers';
|
245 | import 'mapbox-gl/dist/mapbox-gl.css';
|
246 |
|
247 | const myDeckLayer = new MapboxLayer({
|
248 | id: 'my-scatterplot',
|
249 | type: ScatterplotLayer,
|
250 | data: [{ position: [-74.5, 40], size: 1000 }],
|
251 | getPosition: (d) => d.position,
|
252 | getRadius: (d) => d.size,
|
253 | getColor: [255, 0, 0]
|
254 | });
|
255 |
|
256 | <MapGL
|
257 | style={{ width: '100%', height: '400px' }}
|
258 | mapStyle="mapbox://styles/mapbox/light-v9"
|
259 | accessToken={MAPBOX_ACCESS_TOKEN}
|
260 | latitude={40}
|
261 | longitude={-74.5}
|
262 | zoom={9}
|
263 | >
|
264 | <CustomLayer layer={myDeckLayer} />
|
265 | </MapGL>;
|
266 | ```
|
267 |
|
268 | ## Documentation
|
269 |
|
270 | Check out [documentation website](https://urbica.github.io/react-map-gl/).
|
271 |
|
272 | ## Changelog
|
273 |
|
274 | Check out [CHANGELOG.md](CHANGELOG.md) and [releases](https://github.com/urbica/react-map-gl/releases) page.
|
275 |
|
276 | ## License
|
277 |
|
278 | This project is licensed under the terms of the [MIT license](LICENSE).
|
279 |
|
280 | ## Contributing
|
281 |
|
282 | Clone and install dependencies
|
283 |
|
284 | ```shell
|
285 | git clone https://github.com/urbica/react-map-gl.git
|
286 | cd react-map-gl
|
287 | npm install
|
288 | ```
|
289 |
|
290 | Start `react-styleguidist` server
|
291 |
|
292 | ```shell
|
293 | MAPBOX_ACCESS_TOKEN=<TOKEN> npm start
|
294 | ```
|
295 |
|
296 | where `<TOKEN>` is a valid Mapbox [access token](https://www.mapbox.com/help/define-access-token/).
|
297 |
|
298 | Run tests with
|
299 |
|
300 | ```shell
|
301 | npm test
|
302 | ```
|
303 |
|
304 | ## Team
|
305 |
|
306 | | [![Stepan Kuzmin](https://github.com/stepankuzmin.png?size=144)](https://github.com/stepankuzmin) | [![Artem Boyur](https://github.com/boyur.png?size=144)](https://github.com/boyur) | [![Andrey Bakhvalov](https://github.com/device25.png?size=144)](https://github.com/device25) |
|
307 | | ------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
|
308 | | [Stepan Kuzmin](https://github.com/stepankuzmin) | [Artem Boyur](https://github.com/boyur) | [Andrey Bakhvalov](https://github.com/device25) |
|