ºÝºÝߣ

ºÝºÝߣShare a Scribd company logo
§¥§¦§¬§­§¡§²§¡§´§ª§£§¯§½§¦ §¬§¡§²§´§½
§³ REACT §ª MAPBOX GL JS
§³§´§¦§±§¡§¯ §¬§µ§©§¾§®§ª§¯
URBICA
!2
3
URBICA ? MAPBOX
4
VECTOR TILES?
¡ý?
STYLE?
¡ý?
WEBGL
5
VECTOR TILES
6
STYLE
SOURCES
VECTOR
GEOJSON
RASTER
RASTERDEM
VIDEO
IMAGE
LAYERS
FILL
LINE
SYMBOL
CIRCLE
RASTER
FILLEXTRUSION
7
import mapboxgl from 'mapbox-gl';import mapboxgl from 'mapbox-gl';
mapboxgl.accessToken = 'pk ...';
import mapboxgl from 'mapbox-gl';
mapboxgl.accessToken = 'pk ...';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox: //styles/mapbox/streets-v11',
center: [-74.50, 40],
zoom: 9
});
import mapboxgl from 'mapbox-gl';
mapboxgl.accessToken = 'pk ...';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox: //styles/mapbox/streets-v11',
center: [-74.50, 40],
zoom: 9
});
map.on('load', () => {
});
import mapboxgl from 'mapbox-gl';
mapboxgl.accessToken = 'pk ...';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox: //styles/mapbox/streets-v11',
center: [-74.50, 40],
zoom: 9
});
map.on('load', () => {
map.addSource('sourceId', { type: 'vector', url: 'mapbox: // ...' });
});
import mapboxgl from 'mapbox-gl';
mapboxgl.accessToken = 'pk ...';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox: //styles/mapbox/streets-v11',
center: [-74.50, 40],
zoom: 9
});
map.on('load', () => {
map.addSource('sourceId', { type: 'vector', url: 'mapbox: // ...' });
map.addLayer({ id: 'layerId', type: 'line', source: 'sourceId' });
});
import mapboxgl from 'mapbox-gl';
mapboxgl.accessToken = 'pk ...';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox: //styles/mapbox/streets-v11',
center: [-74.50, 40],
zoom: 9
});
map.on('load', () => {
map.addSource('sourceId', { type: 'vector', url: 'mapbox: // ...' });
map.addLayer({ id: 'layerId', type: 'line', source: 'sourceId' });
map.addControl(new mapboxgl.NavigationControl());
});
8
URBICA ? REACT
9
new mapboxgl.Map({ container: 'map' });new mapboxgl.Map({ container: 'map' });
map.on('load', () => {});
new mapboxgl.Map({ container: 'map' });
map.on('load', () => {});
map.addSource('my-source', { type: 'geojson' });
new mapboxgl.Map({ container: 'map' });
map.on('load', () => {});
map.addSource('my-source', { type: 'geojson' });
map.getSource('my-source').setData({});
new mapboxgl.Map({ container: 'map' });
map.on('load', () => {});
map.addSource('my-source', { type: 'geojson' });
map.getSource('my-source').setData({});
map.addLayer({ id: 'my-layer', type: 'line' });
new mapboxgl.Map({ container: 'map' });
map.on('load', () => {});
map.addSource('my-source', { type: 'geojson' });
map.getSource('my-source').setData({});
map.addLayer({ id: 'my-layer', type: 'line' });
map.setLayoutProperty('my-layer', 'visibility', 'none');
new mapboxgl.Map({ container: 'map' });
map.on('load', () => {});
map.addSource('my-source', { type: 'geojson' });
map.getSource('my-source').setData({});
map.addLayer({ id: 'my-layer', type: 'line' });
map.setLayoutProperty('my-layer', 'visibility', 'none');
map.setPaintProperty('my-layer', 'fill-color', '#faafee');
new mapboxgl.Map({ container: 'map' });
map.on('load', () => {});
map.addSource('my-source', { type: 'geojson' });
map.getSource('my-source').setData({});
map.addLayer({ id: 'my-layer', type: 'line' });
map.setLayoutProperty('my-layer', 'visibility', 'none');
map.setPaintProperty('my-layer', 'fill-color', '#faafee');
map.addControl(new mapboxgl.NavigationControl());
10
§¤§°§´§°§£§½§¦ §²§¦§º§¦§¯§ª§Á
GITHUB.COM/UBER/REACT-MAP-GL
GITHUB.COM/ALEX3165/REACT-MAPBOX-GL
11
? §¢§°§­§¾§º§°§« §ª §³§­§°§¨§¯§½§« §±§²§°§¦§¬§´
? §¯§¦§´ §±§°§¥§¥§¦§²§¨§¬§ª CRA (2016)
? §¯§¦§´ §±§°§¥§¥§¦§²§¨§¬§ª SSR (2016)
? §´§Á§¨§¦§­§°§£§¡§´§° (MINZIP 200/50KB)
UBER REACT-MAP-GL
12
ALEX3165 REACT-MAPBOX-GL
? §³§­§¡§¢§¡§Á §´§ª§±§ª§©§¡§¸§ª§Á
? §®§¡§­§° §¬§°§®§±§°§¯§¦§¯§´§°§£ §ª§©
§³§´§¡§¯§¥§¡§²§´§¯§°§« §¢§ª§¢§­§ª§°§´§¦§¬§ª
? §­§¦§¹§¤§¦ (MINZIP 15KB)
13
? §®§¡§¬§³§ª§®§¡§­§¾§¯§° §±§°§·§°§¨§ª§« API
? §£§³§¦ §¬§°§®§±§°§¯§¦§¯§´§½ §ª§©
§³§´§¡§¯§¥§¡§²§´§¯§°§« §¢§ª§¢§­§ª§°§´§¦§¬§ª
? §­§¦§¤§¬§° §²§¡§³§º§ª§²§Á§´§¾
? §£§³§¦§¤§° 6KB MINZIP
@URBICA/REACT-MAP-GL
14
import MapGL, { Source, Layer, NavigationControl }
from '@urbica/react-map-gl';
import MapGL, { Source, Layer, NavigationControl }
from '@urbica/react-map-gl';
<MapGL
mapStyle='mapbox: //styles/mapbox/streets-v11'
latitude={40}
longitude={-74.50}
zoom={9}
>
</MapGL>
import MapGL, { Source, Layer, NavigationControl }
from '@urbica/react-map-gl';
<MapGL
mapStyle='mapbox: //styles/mapbox/streets-v11'
latitude={40}
longitude={-74.50}
zoom={9}
>
<Source id='sourceId' type='vector' url='mapbox: // ...' />
</MapGL>
import MapGL, { Source, Layer, NavigationControl }
from '@urbica/react-map-gl';
<MapGL
mapStyle='mapbox: //styles/mapbox/streets-v11'
latitude={40}
longitude={-74.50}
zoom={9}
>
<Source id='sourceId' type='vector' url='mapbox: // ...' />
<Layer id='layerId' type='line' source='sourceId' paint={ ...} />
</MapGL>
import MapGL, { Source, Layer, NavigationControl }
from '@urbica/react-map-gl';
<MapGL
mapStyle='mapbox: //styles/mapbox/streets-v11'
latitude={40}
longitude={-74.50}
zoom={9}
>
<Source id='sourceId' type='vector' url='mapbox: // ...' />
<Layer id='layerId' type='line' source='sourceId' paint={ ...} />
<NavigationControl />
</MapGL>
15
§±§²§°§¢§­§¦§®§½
16
17
§¯§¦§³§¬§°§­§¾§¬§°?
?§ª§³§´§°§¹§¯§ª§¬§°§£ §±§²§¡§£§¥§½?
18
map.on('moveend', (event) => {
if (event.originalEvent) {
// A human moved the map
}
});
19
Map State?
¡ý?
User?
¡ý?
Event Handler?
¡ý?
onViewportChange?
¡ý?
Map State
20
App State?
¡ý?
componentDidUpdate?
¡ý?
Map State
21
state = {
viewport: {
latitude: 37.78,
longitude: -122.41,
zoom: 11
}
};
<MapGL
mapStyle='mapbox: //styles/mapbox/dark-v9'
onViewportChange={viewport => setState({ viewport })}
viewportChangeMethod={'jumpTo' | 'easeTo' | 'flyTo'}
{ ...state.viewport}
/>
22
§¥§°§¹§¦§²§¯§ª§¦
§¬§°§®§±§°§¯§¦§¯§´§½
23
const mapStyle = Immutable.fromJS({
...baseStyle,
});
<MapGL
mapStyle={mapStyle}
accessToken='pk ...'
onViewportChange={viewport => setState({ viewport })}
{ ...state.viewport}
/>
const mapStyle = Immutable.fromJS({
...baseStyle,
sources: {
...baseStyle.sources,
sourceId1: { type: 'vector', url: 'mapbox: // ...' },
sourceId2: { type: 'geojson', data: {} },
},
});
<MapGL
mapStyle={mapStyle}
accessToken='pk ...'
onViewportChange={viewport => setState({ viewport })}
{ ...state.viewport}
/>
const mapStyle = Immutable.fromJS({
...baseStyle,
sources: {
...baseStyle.sources,
sourceId1: { type: 'vector', url: 'mapbox: // ...' },
sourceId2: { type: 'geojson', data: {} },
},
layers: [
...baseStyle.layers,
{ id: 'layerId1', source: 'sourceId1', type: 'line', paint: {} },
{ id: 'layerId2', source: 'sourceId2', type: 'circle', paint: {} }
]
});
<MapGL
mapStyle={mapStyle}
accessToken='pk ...'
onViewportChange={viewport => setState({ viewport })}
{ ...state.viewport}
/>
24
<MapGL mapStyle='mapbox: //styles/mapbox/streets-v11'>
</MapGL>
<MapGL mapStyle='mapbox: //styles/mapbox/streets-v11'>
<Source id='sourceId1' type='vector' url='mapbox: // ...' />
<Layer id='layerId1' type='line' source='sourceId1' paint={ ...} />
</MapGL>
<MapGL mapStyle='mapbox: //styles/mapbox/streets-v11'>
<Source id='sourceId1' type='vector' url='mapbox: // ...' />
<Layer id='layerId1' type='line' source='sourceId1' paint={ ...} />
<Source id='sourceId2' type='vector' url='mapbox: // ...' />
<Layer id='layerId2' type='circle' source='sourceId2' paint={ ...} />
</MapGL>
<MapGL mapStyle='mapbox: //styles/mapbox/streets-v11'>
<Source id='sourceId1' type='vector' url='mapbox: // ...' />
<Layer id='layerId1' type='line' source='sourceId1' paint={ ...} />
<Source id='sourceId2' type='vector' url='mapbox: // ...' />
<Layer id='layerId2' type='circle' source='sourceId2' paint={ ...} />
<FullscreenControl />
<NavigationControl />
</MapGL>
25
const MapContext = React.createContext(null);const MapContext = React.createContext(null);
<MapContext.Provider value={this._map}>
</MapContext.Provider>
const MapContext = React.createContext(null);
<MapContext.Provider value={this._map}>
<MapContext.Consumer>
</MapContext.Consumer>
</MapContext.Provider>
const MapContext = React.createContext(null);
<MapContext.Provider value={this._map}>
<MapContext.Consumer>
{(map) => this._map = map}
</MapContext.Consumer>
</MapContext.Provider>
26
§±§°§²§Á§¥§°§¬
§°§´§²§ª§³§°§£§¬§ª
§³§­§°§§§£
27
// normalizeChildren
const layerWithBefore = cloneElement(layer, {
before: layer.props.before || nextLayerId;
});
const children = this.props.children
? normalizeChildren(this.props.children)
: null;
28
§µ§¥§¡§­§¦§¯§ª§¦
§ª§³§´§°§¹§¯§ª§¬§°§£ §¥§¡§¯§¯§½§·
29
_removeSource = () => {
const sourceId = this.props.id;
const { layers } = this._map.getStyle();
layers.forEach((layer) => {
if (layer.source === sourceId) {
this._map.removeLayer(layer.id);
}
});
this._map.removeSource(sourceId);
};
30
§¬§°§®§±§°§¯§¦§¯§´§½
31
<Source
id='sourceId'
type='vector'
url='mapbox: //mapbox-terrain-v2'
attribution='? Urbica'
/>
<Source
id='sourceId'
type='geojson'
data='https: // ...'
attribution='? Urbica'
/>
<Source
id='sourceId'
type='raster'
tileSize={256}
tiles={['https: // ...']}
/>
<Source
id='sourceId'
type='video'
urls={['https: // ...']}
coordinates={[]}
/>
<Source
id='sourceId'
type='image'
url='https: // ...'
coordinates={[]}
/>
32
<Layer
id='layerId'
type='line'
source='sourceId'
paint={{
'line-color': '#877b59',
'line-width': 1
}}
/>
<Layer
id='layerId'
type='circle'
source='sourceId'
paint={{
'circle-color': '#877b59',
'circle-width': 1
}}
/>
<Layer
id='layerId'
type='fill'
source='sourceId'
paint={{
'fill-color': '#877b59',
'fill-opacity': 0.8
}}
/>
<Layer
id='layerId'
type='symbol'
source='sourceId'
paint={{
'text-color': '#877b59',
'text-field': 'name:ru'
}}
/>
33
import { MapboxLayer } from '@deck.gl/mapbox';
import { ScatterplotLayer } from '@deck.gl/layers';
import MapGL, { CustomLayer } from '@urbica/react-map-gl';
const myDeckLayer = new MapboxLayer({
id: 'my-scatterplot',
type: ScatterplotLayer,
data: [{ position: [-74.5, 40], size: 1000 }],
getPosition: d => d.position,
getRadius: d => d.size,
getColor: [255, 0, 0]
});
<MapGL mapStyle='mapbox: // ...'>
<CustomLayer layer={myDeckLayer} />
</MapGL>
34
<MapGL mapStyle='mapbox: // ...'>
<AttributionControl />
<FullscreenControl />
<GeolocateControl />
<NavigationControl />?
<LanguageControl />
</MapGL>
35
<MapGL mapStyle='mapbox: // ...'>
<Source id='sourceId' />
<Layer id='layerId' />
<FeatureState
id={state.featureId}
source='sourceId'
state={{ hover: true }}
/>
</MapGL>
36
<MapGL mapStyle='mapbox: // ...'>
<Popup longitude={0} latitude={0}>
Hi there! ?
</Popup>
</MapGL>
37
<MapGL mapStyle='mapbox: // ...'>
<Marker longitude={0} latitude={0}>
<svg><circle fill='red' r='60' /> </svg>
</Marker>
</MapGL>
38
<MapGL mapStyle='mapbox: //styles/mapbox/light-v9'>
<Cluster radius={40} extent={512} nodeSize={64}>
{points.map(point => (
<Marker
key={point.id}
longitude={point.geometry.coordinates[0]}
latitude={point.geometry.coordinates[1]}
/>
))}
</Cluster>
</MapGL>
39
state = {
data: {
type: 'FeatureCollection',
features: []
}
}
<Draw
data={state.data}
mode='simple_select'
onChange={(data) => setState({ data })}
/>
40
§³§±§¡§³§ª§¢§°
stepan@urbica.co
github.com/stepankuzmin
github.com/urbica/react-map-gl?
github.com/urbica/react-map-gl-draw?
github.com/urbica/react-map-gl-cluster?
?
github.com/mapbox/mapbox-gl?
github.com/mapbox/vector-tile-spec?
github.com/mapbox/mapbox-gl-style-spec

More Related Content

Declarative maps with React and Mapbox GL JS

  • 1. §¥§¦§¬§­§¡§²§¡§´§ª§£§¯§½§¦ §¬§¡§²§´§½ §³ REACT §ª MAPBOX GL JS §³§´§¦§±§¡§¯ §¬§µ§©§¾§®§ª§¯ URBICA
  • 2. !2
  • 7. 7 import mapboxgl from 'mapbox-gl';import mapboxgl from 'mapbox-gl'; mapboxgl.accessToken = 'pk ...'; import mapboxgl from 'mapbox-gl'; mapboxgl.accessToken = 'pk ...'; const map = new mapboxgl.Map({ container: 'map', style: 'mapbox: //styles/mapbox/streets-v11', center: [-74.50, 40], zoom: 9 }); import mapboxgl from 'mapbox-gl'; mapboxgl.accessToken = 'pk ...'; const map = new mapboxgl.Map({ container: 'map', style: 'mapbox: //styles/mapbox/streets-v11', center: [-74.50, 40], zoom: 9 }); map.on('load', () => { }); import mapboxgl from 'mapbox-gl'; mapboxgl.accessToken = 'pk ...'; const map = new mapboxgl.Map({ container: 'map', style: 'mapbox: //styles/mapbox/streets-v11', center: [-74.50, 40], zoom: 9 }); map.on('load', () => { map.addSource('sourceId', { type: 'vector', url: 'mapbox: // ...' }); }); import mapboxgl from 'mapbox-gl'; mapboxgl.accessToken = 'pk ...'; const map = new mapboxgl.Map({ container: 'map', style: 'mapbox: //styles/mapbox/streets-v11', center: [-74.50, 40], zoom: 9 }); map.on('load', () => { map.addSource('sourceId', { type: 'vector', url: 'mapbox: // ...' }); map.addLayer({ id: 'layerId', type: 'line', source: 'sourceId' }); }); import mapboxgl from 'mapbox-gl'; mapboxgl.accessToken = 'pk ...'; const map = new mapboxgl.Map({ container: 'map', style: 'mapbox: //styles/mapbox/streets-v11', center: [-74.50, 40], zoom: 9 }); map.on('load', () => { map.addSource('sourceId', { type: 'vector', url: 'mapbox: // ...' }); map.addLayer({ id: 'layerId', type: 'line', source: 'sourceId' }); map.addControl(new mapboxgl.NavigationControl()); });
  • 9. 9 new mapboxgl.Map({ container: 'map' });new mapboxgl.Map({ container: 'map' }); map.on('load', () => {}); new mapboxgl.Map({ container: 'map' }); map.on('load', () => {}); map.addSource('my-source', { type: 'geojson' }); new mapboxgl.Map({ container: 'map' }); map.on('load', () => {}); map.addSource('my-source', { type: 'geojson' }); map.getSource('my-source').setData({}); new mapboxgl.Map({ container: 'map' }); map.on('load', () => {}); map.addSource('my-source', { type: 'geojson' }); map.getSource('my-source').setData({}); map.addLayer({ id: 'my-layer', type: 'line' }); new mapboxgl.Map({ container: 'map' }); map.on('load', () => {}); map.addSource('my-source', { type: 'geojson' }); map.getSource('my-source').setData({}); map.addLayer({ id: 'my-layer', type: 'line' }); map.setLayoutProperty('my-layer', 'visibility', 'none'); new mapboxgl.Map({ container: 'map' }); map.on('load', () => {}); map.addSource('my-source', { type: 'geojson' }); map.getSource('my-source').setData({}); map.addLayer({ id: 'my-layer', type: 'line' }); map.setLayoutProperty('my-layer', 'visibility', 'none'); map.setPaintProperty('my-layer', 'fill-color', '#faafee'); new mapboxgl.Map({ container: 'map' }); map.on('load', () => {}); map.addSource('my-source', { type: 'geojson' }); map.getSource('my-source').setData({}); map.addLayer({ id: 'my-layer', type: 'line' }); map.setLayoutProperty('my-layer', 'visibility', 'none'); map.setPaintProperty('my-layer', 'fill-color', '#faafee'); map.addControl(new mapboxgl.NavigationControl());
  • 11. 11 ? §¢§°§­§¾§º§°§« §ª §³§­§°§¨§¯§½§« §±§²§°§¦§¬§´ ? §¯§¦§´ §±§°§¥§¥§¦§²§¨§¬§ª CRA (2016) ? §¯§¦§´ §±§°§¥§¥§¦§²§¨§¬§ª SSR (2016) ? §´§Á§¨§¦§­§°§£§¡§´§° (MINZIP 200/50KB) UBER REACT-MAP-GL
  • 12. 12 ALEX3165 REACT-MAPBOX-GL ? §³§­§¡§¢§¡§Á §´§ª§±§ª§©§¡§¸§ª§Á ? §®§¡§­§° §¬§°§®§±§°§¯§¦§¯§´§°§£ §ª§© §³§´§¡§¯§¥§¡§²§´§¯§°§« §¢§ª§¢§­§ª§°§´§¦§¬§ª ? §­§¦§¹§¤§¦ (MINZIP 15KB)
  • 13. 13 ? §®§¡§¬§³§ª§®§¡§­§¾§¯§° §±§°§·§°§¨§ª§« API ? §£§³§¦ §¬§°§®§±§°§¯§¦§¯§´§½ §ª§© §³§´§¡§¯§¥§¡§²§´§¯§°§« §¢§ª§¢§­§ª§°§´§¦§¬§ª ? §­§¦§¤§¬§° §²§¡§³§º§ª§²§Á§´§¾ ? §£§³§¦§¤§° 6KB MINZIP @URBICA/REACT-MAP-GL
  • 14. 14 import MapGL, { Source, Layer, NavigationControl } from '@urbica/react-map-gl'; import MapGL, { Source, Layer, NavigationControl } from '@urbica/react-map-gl'; <MapGL mapStyle='mapbox: //styles/mapbox/streets-v11' latitude={40} longitude={-74.50} zoom={9} > </MapGL> import MapGL, { Source, Layer, NavigationControl } from '@urbica/react-map-gl'; <MapGL mapStyle='mapbox: //styles/mapbox/streets-v11' latitude={40} longitude={-74.50} zoom={9} > <Source id='sourceId' type='vector' url='mapbox: // ...' /> </MapGL> import MapGL, { Source, Layer, NavigationControl } from '@urbica/react-map-gl'; <MapGL mapStyle='mapbox: //styles/mapbox/streets-v11' latitude={40} longitude={-74.50} zoom={9} > <Source id='sourceId' type='vector' url='mapbox: // ...' /> <Layer id='layerId' type='line' source='sourceId' paint={ ...} /> </MapGL> import MapGL, { Source, Layer, NavigationControl } from '@urbica/react-map-gl'; <MapGL mapStyle='mapbox: //styles/mapbox/streets-v11' latitude={40} longitude={-74.50} zoom={9} > <Source id='sourceId' type='vector' url='mapbox: // ...' /> <Layer id='layerId' type='line' source='sourceId' paint={ ...} /> <NavigationControl /> </MapGL>
  • 16. 16
  • 18. 18 map.on('moveend', (event) => { if (event.originalEvent) { // A human moved the map } });
  • 21. 21 state = { viewport: { latitude: 37.78, longitude: -122.41, zoom: 11 } }; <MapGL mapStyle='mapbox: //styles/mapbox/dark-v9' onViewportChange={viewport => setState({ viewport })} viewportChangeMethod={'jumpTo' | 'easeTo' | 'flyTo'} { ...state.viewport} />
  • 23. 23 const mapStyle = Immutable.fromJS({ ...baseStyle, }); <MapGL mapStyle={mapStyle} accessToken='pk ...' onViewportChange={viewport => setState({ viewport })} { ...state.viewport} /> const mapStyle = Immutable.fromJS({ ...baseStyle, sources: { ...baseStyle.sources, sourceId1: { type: 'vector', url: 'mapbox: // ...' }, sourceId2: { type: 'geojson', data: {} }, }, }); <MapGL mapStyle={mapStyle} accessToken='pk ...' onViewportChange={viewport => setState({ viewport })} { ...state.viewport} /> const mapStyle = Immutable.fromJS({ ...baseStyle, sources: { ...baseStyle.sources, sourceId1: { type: 'vector', url: 'mapbox: // ...' }, sourceId2: { type: 'geojson', data: {} }, }, layers: [ ...baseStyle.layers, { id: 'layerId1', source: 'sourceId1', type: 'line', paint: {} }, { id: 'layerId2', source: 'sourceId2', type: 'circle', paint: {} } ] }); <MapGL mapStyle={mapStyle} accessToken='pk ...' onViewportChange={viewport => setState({ viewport })} { ...state.viewport} />
  • 24. 24 <MapGL mapStyle='mapbox: //styles/mapbox/streets-v11'> </MapGL> <MapGL mapStyle='mapbox: //styles/mapbox/streets-v11'> <Source id='sourceId1' type='vector' url='mapbox: // ...' /> <Layer id='layerId1' type='line' source='sourceId1' paint={ ...} /> </MapGL> <MapGL mapStyle='mapbox: //styles/mapbox/streets-v11'> <Source id='sourceId1' type='vector' url='mapbox: // ...' /> <Layer id='layerId1' type='line' source='sourceId1' paint={ ...} /> <Source id='sourceId2' type='vector' url='mapbox: // ...' /> <Layer id='layerId2' type='circle' source='sourceId2' paint={ ...} /> </MapGL> <MapGL mapStyle='mapbox: //styles/mapbox/streets-v11'> <Source id='sourceId1' type='vector' url='mapbox: // ...' /> <Layer id='layerId1' type='line' source='sourceId1' paint={ ...} /> <Source id='sourceId2' type='vector' url='mapbox: // ...' /> <Layer id='layerId2' type='circle' source='sourceId2' paint={ ...} /> <FullscreenControl /> <NavigationControl /> </MapGL>
  • 25. 25 const MapContext = React.createContext(null);const MapContext = React.createContext(null); <MapContext.Provider value={this._map}> </MapContext.Provider> const MapContext = React.createContext(null); <MapContext.Provider value={this._map}> <MapContext.Consumer> </MapContext.Consumer> </MapContext.Provider> const MapContext = React.createContext(null); <MapContext.Provider value={this._map}> <MapContext.Consumer> {(map) => this._map = map} </MapContext.Consumer> </MapContext.Provider>
  • 27. 27 // normalizeChildren const layerWithBefore = cloneElement(layer, { before: layer.props.before || nextLayerId; }); const children = this.props.children ? normalizeChildren(this.props.children) : null;
  • 29. 29 _removeSource = () => { const sourceId = this.props.id; const { layers } = this._map.getStyle(); layers.forEach((layer) => { if (layer.source === sourceId) { this._map.removeLayer(layer.id); } }); this._map.removeSource(sourceId); };
  • 31. 31 <Source id='sourceId' type='vector' url='mapbox: //mapbox-terrain-v2' attribution='? Urbica' /> <Source id='sourceId' type='geojson' data='https: // ...' attribution='? Urbica' /> <Source id='sourceId' type='raster' tileSize={256} tiles={['https: // ...']} /> <Source id='sourceId' type='video' urls={['https: // ...']} coordinates={[]} /> <Source id='sourceId' type='image' url='https: // ...' coordinates={[]} />
  • 32. 32 <Layer id='layerId' type='line' source='sourceId' paint={{ 'line-color': '#877b59', 'line-width': 1 }} /> <Layer id='layerId' type='circle' source='sourceId' paint={{ 'circle-color': '#877b59', 'circle-width': 1 }} /> <Layer id='layerId' type='fill' source='sourceId' paint={{ 'fill-color': '#877b59', 'fill-opacity': 0.8 }} /> <Layer id='layerId' type='symbol' source='sourceId' paint={{ 'text-color': '#877b59', 'text-field': 'name:ru' }} />
  • 33. 33 import { MapboxLayer } from '@deck.gl/mapbox'; import { ScatterplotLayer } from '@deck.gl/layers'; import MapGL, { CustomLayer } from '@urbica/react-map-gl'; const myDeckLayer = new MapboxLayer({ id: 'my-scatterplot', type: ScatterplotLayer, data: [{ position: [-74.5, 40], size: 1000 }], getPosition: d => d.position, getRadius: d => d.size, getColor: [255, 0, 0] }); <MapGL mapStyle='mapbox: // ...'> <CustomLayer layer={myDeckLayer} /> </MapGL>
  • 34. 34 <MapGL mapStyle='mapbox: // ...'> <AttributionControl /> <FullscreenControl /> <GeolocateControl /> <NavigationControl />? <LanguageControl /> </MapGL>
  • 35. 35 <MapGL mapStyle='mapbox: // ...'> <Source id='sourceId' /> <Layer id='layerId' /> <FeatureState id={state.featureId} source='sourceId' state={{ hover: true }} /> </MapGL>
  • 36. 36 <MapGL mapStyle='mapbox: // ...'> <Popup longitude={0} latitude={0}> Hi there! ? </Popup> </MapGL>
  • 37. 37 <MapGL mapStyle='mapbox: // ...'> <Marker longitude={0} latitude={0}> <svg><circle fill='red' r='60' /> </svg> </Marker> </MapGL>
  • 38. 38 <MapGL mapStyle='mapbox: //styles/mapbox/light-v9'> <Cluster radius={40} extent={512} nodeSize={64}> {points.map(point => ( <Marker key={point.id} longitude={point.geometry.coordinates[0]} latitude={point.geometry.coordinates[1]} /> ))} </Cluster> </MapGL>
  • 39. 39 state = { data: { type: 'FeatureCollection', features: [] } } <Draw data={state.data} mode='simple_select' onChange={(data) => setState({ data })} />