mirror of
https://github.com/visgl/react-map-gl.git
synced 2026-01-25 16:02:50 +00:00
Use JSX sources/layers in examples (PR 2/2) (#897)
This commit is contained in:
parent
2c6672593c
commit
ca0796a74f
@ -4,7 +4,6 @@
|
||||
"start-local": "webpack-dev-server --env.local --progress --hot --open"
|
||||
},
|
||||
"dependencies": {
|
||||
"immutable": "^3.8.1",
|
||||
"react": "^16.3.0",
|
||||
"react-dom": "^16.3.0",
|
||||
"react-map-gl": "^5.0.0"
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import React, {Component} from 'react';
|
||||
import {render} from 'react-dom';
|
||||
import MapGL, {Popup} from 'react-map-gl';
|
||||
import MapGL, {Popup, Source, Layer} from 'react-map-gl';
|
||||
import ControlPanel from './control-panel';
|
||||
|
||||
import {defaultMapStyle, highlightLayerIndex} from './map-style.js';
|
||||
import {countiesLayer, highlightLayer} from './map-style.js';
|
||||
|
||||
const MAPBOX_TOKEN = ''; // Set your mapbox token here
|
||||
|
||||
export default class App extends Component {
|
||||
state = {
|
||||
mapStyle: defaultMapStyle,
|
||||
filter: ['in', 'COUNTY', ''],
|
||||
viewport: {
|
||||
latitude: 38.88,
|
||||
longitude: -98,
|
||||
@ -27,7 +27,7 @@ export default class App extends Component {
|
||||
let countyName = '';
|
||||
let hoverInfo = null;
|
||||
|
||||
const county = event.features && event.features.find(f => f.layer.id === 'counties');
|
||||
const county = event.features[0];
|
||||
if (county) {
|
||||
hoverInfo = {
|
||||
lngLat: event.lngLat,
|
||||
@ -36,7 +36,7 @@ export default class App extends Component {
|
||||
countyName = county.properties.COUNTY;
|
||||
}
|
||||
this.setState({
|
||||
mapStyle: defaultMapStyle.setIn(['layers', highlightLayerIndex, 'filter', 2], countyName),
|
||||
filter: ['in', 'COUNTY', countyName],
|
||||
hoverInfo
|
||||
});
|
||||
};
|
||||
@ -54,18 +54,23 @@ export default class App extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const {viewport, mapStyle} = this.state;
|
||||
const {viewport, filter} = this.state;
|
||||
|
||||
return (
|
||||
<MapGL
|
||||
{...viewport}
|
||||
width="100%"
|
||||
height="100%"
|
||||
mapStyle={mapStyle}
|
||||
mapStyle="mapbox://styles/mapbox/light-v9"
|
||||
mapboxApiAccessToken={MAPBOX_TOKEN}
|
||||
onViewportChange={this._onViewportChange}
|
||||
onHover={this._onHover}
|
||||
interactiveLayerIds={['counties']}
|
||||
>
|
||||
<Source type="vector" url="mapbox://mapbox.82pkq93d">
|
||||
<Layer beforeId="waterway-label" {...countiesLayer} />
|
||||
<Layer beforeId="waterway-label" {...highlightLayer} filter={filter} />
|
||||
</Source>
|
||||
{this._renderPopup()}
|
||||
<ControlPanel containerComponent={this.props.containerComponent} />
|
||||
</MapGL>
|
||||
|
||||
@ -1,52 +1,21 @@
|
||||
import {fromJS} from 'immutable';
|
||||
import MAP_STYLE from '../../map-style-basic-v8.json';
|
||||
|
||||
// Make a copy of the map style
|
||||
const mapStyle = {
|
||||
...MAP_STYLE,
|
||||
sources: {...MAP_STYLE.sources},
|
||||
layers: MAP_STYLE.layers.slice()
|
||||
};
|
||||
|
||||
// Add the vector tile source for counties
|
||||
mapStyle.sources.counties = {
|
||||
type: 'vector',
|
||||
url: 'mapbox://mapbox.82pkq93d'
|
||||
};
|
||||
|
||||
// Insert custom layers before city labels
|
||||
mapStyle.layers.splice(
|
||||
mapStyle.layers.findIndex(layer => layer.id === 'place_label_city'),
|
||||
0,
|
||||
// Counties polygons
|
||||
{
|
||||
id: 'counties',
|
||||
interactive: true,
|
||||
type: 'fill',
|
||||
source: 'counties',
|
||||
'source-layer': 'original',
|
||||
paint: {
|
||||
'fill-outline-color': 'rgba(0,0,0,0.1)',
|
||||
'fill-color': 'rgba(0,0,0,0.1)'
|
||||
}
|
||||
},
|
||||
// Highlighted county polygons
|
||||
{
|
||||
id: 'counties-highlighted',
|
||||
type: 'fill',
|
||||
source: 'counties',
|
||||
'source-layer': 'original',
|
||||
paint: {
|
||||
'fill-outline-color': '#484896',
|
||||
'fill-color': '#6e599f',
|
||||
'fill-opacity': 0.75
|
||||
},
|
||||
filter: ['in', 'COUNTY', '']
|
||||
export const countiesLayer = {
|
||||
id: 'counties',
|
||||
type: 'fill',
|
||||
'source-layer': 'original',
|
||||
paint: {
|
||||
'fill-outline-color': 'rgba(0,0,0,0.1)',
|
||||
'fill-color': 'rgba(0,0,0,0.1)'
|
||||
}
|
||||
);
|
||||
|
||||
export const highlightLayerIndex = mapStyle.layers.findIndex(
|
||||
layer => layer.id === 'counties-highlighted'
|
||||
);
|
||||
|
||||
export const defaultMapStyle = fromJS(mapStyle);
|
||||
};
|
||||
// Highlighted county polygons
|
||||
export const highlightLayer = {
|
||||
id: 'counties-highlighted',
|
||||
type: 'fill',
|
||||
source: 'counties',
|
||||
'source-layer': 'original',
|
||||
paint: {
|
||||
'fill-outline-color': '#484896',
|
||||
'fill-color': '#6e599f',
|
||||
'fill-opacity': 0.75
|
||||
}
|
||||
};
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
"start-local": "webpack-dev-server --env.local --progress --hot --open"
|
||||
},
|
||||
"dependencies": {
|
||||
"immutable": "^3.8.1",
|
||||
"react": "^16.3.0",
|
||||
"react-dom": "^16.3.0",
|
||||
"react-map-gl": "^5.0.0"
|
||||
|
||||
@ -1,20 +1,24 @@
|
||||
/* global window */
|
||||
import React, {Component} from 'react';
|
||||
import {render} from 'react-dom';
|
||||
import MapGL from 'react-map-gl';
|
||||
import MapGL, {Source, Layer} from 'react-map-gl';
|
||||
|
||||
import ControlPanel from './control-panel';
|
||||
import {defaultMapStyle, pointLayer} from './map-style.js';
|
||||
import {pointOnCircle} from './utils';
|
||||
import {fromJS} from 'immutable';
|
||||
|
||||
const MAPBOX_TOKEN = ''; // Set your mapbox token here
|
||||
|
||||
let animation = null;
|
||||
const pointLayer = {
|
||||
type: 'circle',
|
||||
paint: {
|
||||
'circle-radius': 10,
|
||||
'circle-color': '#007cbf'
|
||||
}
|
||||
};
|
||||
|
||||
export default class App extends Component {
|
||||
state = {
|
||||
mapStyle: defaultMapStyle,
|
||||
pointData: null,
|
||||
viewport: {
|
||||
latitude: 0,
|
||||
longitude: -100,
|
||||
@ -25,47 +29,41 @@ export default class App extends Component {
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
animation = window.requestAnimationFrame(this._animatePoint);
|
||||
this._animatePoint();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.cancelAnimationFrame(animation);
|
||||
window.cancelAnimationFrame(this.animation);
|
||||
}
|
||||
|
||||
animation = null;
|
||||
|
||||
_animatePoint = () => {
|
||||
this._updatePointData(pointOnCircle({center: [-100, 0], angle: Date.now() / 1000, radius: 20}));
|
||||
animation = window.requestAnimationFrame(this._animatePoint);
|
||||
};
|
||||
|
||||
_updatePointData = pointData => {
|
||||
let {mapStyle} = this.state;
|
||||
if (!mapStyle.hasIn(['sources', 'point'])) {
|
||||
mapStyle = mapStyle
|
||||
// Add geojson source to map
|
||||
.setIn(['sources', 'point'], fromJS({type: 'geojson'}))
|
||||
// Add point layer to map
|
||||
.set('layers', mapStyle.get('layers').push(pointLayer));
|
||||
}
|
||||
// Update data source
|
||||
mapStyle = mapStyle.setIn(['sources', 'point', 'data'], pointData);
|
||||
|
||||
this.setState({mapStyle});
|
||||
this.setState({
|
||||
pointData: pointOnCircle({center: [-100, 0], angle: Date.now() / 1000, radius: 20})
|
||||
});
|
||||
this.animation = window.requestAnimationFrame(this._animatePoint);
|
||||
};
|
||||
|
||||
_onViewportChange = viewport => this.setState({viewport});
|
||||
|
||||
render() {
|
||||
const {viewport, mapStyle} = this.state;
|
||||
const {viewport, pointData} = this.state;
|
||||
|
||||
return (
|
||||
<MapGL
|
||||
{...viewport}
|
||||
width="100%"
|
||||
height="100%"
|
||||
mapStyle={mapStyle}
|
||||
mapStyle="mapbox://styles/mapbox/light-v9"
|
||||
onViewportChange={this._onViewportChange}
|
||||
mapboxApiAccessToken={MAPBOX_TOKEN}
|
||||
>
|
||||
{pointData && (
|
||||
<Source type="geojson" data={pointData}>
|
||||
<Layer {...pointLayer} />
|
||||
</Source>
|
||||
)}
|
||||
<ControlPanel containerComponent={this.props.containerComponent} />
|
||||
</MapGL>
|
||||
);
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
import {fromJS} from 'immutable';
|
||||
import MAP_STYLE from '../../map-style-basic-v8.json';
|
||||
|
||||
export const pointLayer = fromJS({
|
||||
id: 'point',
|
||||
source: 'point',
|
||||
type: 'circle',
|
||||
paint: {
|
||||
'circle-radius': 10,
|
||||
'circle-color': '#007cbf'
|
||||
}
|
||||
});
|
||||
|
||||
export const defaultMapStyle = fromJS(MAP_STYLE);
|
||||
@ -6,7 +6,6 @@
|
||||
"dependencies": {
|
||||
"d3-request": "^1.0.5",
|
||||
"d3-scale": "^1.0.6",
|
||||
"immutable": "^3.8.1",
|
||||
"react": "^16.3.0",
|
||||
"react-dom": "^16.3.0",
|
||||
"react-map-gl": "^5.0.0"
|
||||
|
||||
@ -1,18 +1,16 @@
|
||||
import React, {Component} from 'react';
|
||||
import {render} from 'react-dom';
|
||||
import MapGL from 'react-map-gl';
|
||||
import MapGL, {Source, Layer} from 'react-map-gl';
|
||||
import ControlPanel from './control-panel';
|
||||
|
||||
import {defaultMapStyle, dataLayer} from './map-style.js';
|
||||
import {dataLayer} from './map-style.js';
|
||||
import {updatePercentiles} from './utils';
|
||||
import {fromJS} from 'immutable';
|
||||
import {json as requestJson} from 'd3-request';
|
||||
|
||||
const MAPBOX_TOKEN = ''; // Set your mapbox token here
|
||||
|
||||
export default class App extends Component {
|
||||
state = {
|
||||
mapStyle: defaultMapStyle,
|
||||
year: 2015,
|
||||
data: null,
|
||||
hoveredFeature: null,
|
||||
@ -35,25 +33,18 @@ export default class App extends Component {
|
||||
|
||||
_loadData = data => {
|
||||
updatePercentiles(data, f => f.properties.income[this.state.year]);
|
||||
|
||||
const mapStyle = defaultMapStyle
|
||||
// Add geojson source to map
|
||||
.setIn(['sources', 'incomeByState'], fromJS({type: 'geojson', data}))
|
||||
// Add point layer to map
|
||||
.set('layers', defaultMapStyle.get('layers').push(dataLayer));
|
||||
|
||||
this.setState({data, mapStyle});
|
||||
this.setState({data});
|
||||
};
|
||||
|
||||
_updateSettings = (name, value) => {
|
||||
if (name === 'year') {
|
||||
this.setState({year: value});
|
||||
|
||||
const {data, mapStyle} = this.state;
|
||||
const {data} = this.state;
|
||||
if (data) {
|
||||
updatePercentiles(data, f => f.properties.income[value]);
|
||||
const newMapStyle = mapStyle.setIn(['sources', 'incomeByState', 'data'], fromJS(data));
|
||||
this.setState({mapStyle: newMapStyle});
|
||||
// trigger update
|
||||
this.setState({data: {...data}});
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -85,7 +76,7 @@ export default class App extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const {viewport, mapStyle} = this.state;
|
||||
const {viewport, data} = this.state;
|
||||
|
||||
return (
|
||||
<div style={{height: '100%'}}>
|
||||
@ -93,11 +84,14 @@ export default class App extends Component {
|
||||
{...viewport}
|
||||
width="100%"
|
||||
height="100%"
|
||||
mapStyle={mapStyle}
|
||||
mapStyle="mapbox://styles/mapbox/light-v9"
|
||||
onViewportChange={this._onViewportChange}
|
||||
mapboxApiAccessToken={MAPBOX_TOKEN}
|
||||
onHover={this._onHover}
|
||||
>
|
||||
<Source type="geojson" data={data}>
|
||||
<Layer {...dataLayer} />
|
||||
</Source>
|
||||
{this._renderTooltip()}
|
||||
</MapGL>
|
||||
|
||||
|
||||
@ -1,12 +1,7 @@
|
||||
import {fromJS} from 'immutable';
|
||||
import MAP_STYLE from '../../map-style-basic-v8.json';
|
||||
|
||||
// For more information on data-driven styles, see https://www.mapbox.com/help/gl-dds-ref/
|
||||
export const dataLayer = fromJS({
|
||||
export const dataLayer = {
|
||||
id: 'data',
|
||||
source: 'incomeByState',
|
||||
type: 'fill',
|
||||
interactive: true,
|
||||
paint: {
|
||||
'fill-color': {
|
||||
property: 'percentile',
|
||||
@ -24,6 +19,4 @@ export const dataLayer = fromJS({
|
||||
},
|
||||
'fill-opacity': 0.8
|
||||
}
|
||||
});
|
||||
|
||||
export const defaultMapStyle = fromJS(MAP_STYLE);
|
||||
};
|
||||
|
||||
@ -1,11 +1,27 @@
|
||||
import React, {Component} from 'react';
|
||||
import {render} from 'react-dom';
|
||||
import MapGL from 'react-map-gl';
|
||||
import MapGL, {Source, Layer} from 'react-map-gl';
|
||||
import ControlPanel from './control-panel';
|
||||
import {json as requestJson} from 'd3-request';
|
||||
import {heatmapLayer} from './map-style';
|
||||
|
||||
const MAPBOX_TOKEN = ''; // Set your mapbox token here
|
||||
const HEATMAP_SOURCE_ID = 'earthquakes-source';
|
||||
|
||||
function filterFeaturesByDay(featureCollection, time) {
|
||||
const date = new Date(time);
|
||||
const year = date.getFullYear();
|
||||
const month = date.getMonth();
|
||||
const day = date.getDate();
|
||||
const features = featureCollection.features.filter(feature => {
|
||||
const featureDate = new Date(feature.properties.time);
|
||||
return (
|
||||
featureDate.getFullYear() === year &&
|
||||
featureDate.getMonth() === month &&
|
||||
featureDate.getDate() === day
|
||||
);
|
||||
});
|
||||
return {type: 'FeatureCollection', features};
|
||||
}
|
||||
|
||||
export default class App extends Component {
|
||||
constructor(props) {
|
||||
@ -27,79 +43,11 @@ export default class App extends Component {
|
||||
earthquakes: null
|
||||
};
|
||||
|
||||
this._mapRef = React.createRef();
|
||||
this._handleMapLoaded = this._handleMapLoaded.bind(this);
|
||||
this._handleChangeDay = this._handleChangeDay.bind(this);
|
||||
this._handleChangeAllDay = this._handleChangeAllDay.bind(this);
|
||||
}
|
||||
|
||||
_mkFeatureCollection = features => ({type: 'FeatureCollection', features});
|
||||
|
||||
_filterFeaturesByDay = (features, time) => {
|
||||
const date = new Date(time);
|
||||
const year = date.getFullYear();
|
||||
const month = date.getMonth();
|
||||
const day = date.getDate();
|
||||
return features.filter(feature => {
|
||||
const featureDate = new Date(feature.properties.time);
|
||||
return (
|
||||
featureDate.getFullYear() === year &&
|
||||
featureDate.getMonth() === month &&
|
||||
featureDate.getDate() === day
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
_mkHeatmapLayer = (id, source) => {
|
||||
const MAX_ZOOM_LEVEL = 9;
|
||||
return {
|
||||
id,
|
||||
source,
|
||||
maxzoom: MAX_ZOOM_LEVEL,
|
||||
type: 'heatmap',
|
||||
paint: {
|
||||
// Increase the heatmap weight based on frequency and property magnitude
|
||||
'heatmap-weight': ['interpolate', ['linear'], ['get', 'mag'], 0, 0, 6, 1],
|
||||
// Increase the heatmap color weight weight by zoom level
|
||||
// heatmap-intensity is a multiplier on top of heatmap-weight
|
||||
'heatmap-intensity': ['interpolate', ['linear'], ['zoom'], 0, 1, MAX_ZOOM_LEVEL, 3],
|
||||
// Color ramp for heatmap. Domain is 0 (low) to 1 (high).
|
||||
// Begin color ramp at 0-stop with a 0-transparancy color
|
||||
// to create a blur-like effect.
|
||||
'heatmap-color': [
|
||||
'interpolate',
|
||||
['linear'],
|
||||
['heatmap-density'],
|
||||
0,
|
||||
'rgba(33,102,172,0)',
|
||||
0.2,
|
||||
'rgb(103,169,207)',
|
||||
0.4,
|
||||
'rgb(209,229,240)',
|
||||
0.6,
|
||||
'rgb(253,219,199)',
|
||||
0.8,
|
||||
'rgb(239,138,98)',
|
||||
0.9,
|
||||
'rgb(255,201,101)'
|
||||
],
|
||||
// Adjust the heatmap radius by zoom level
|
||||
'heatmap-radius': ['interpolate', ['linear'], ['zoom'], 0, 2, MAX_ZOOM_LEVEL, 20],
|
||||
// Transition from heatmap to circle layer by zoom level
|
||||
'heatmap-opacity': ['interpolate', ['linear'], ['zoom'], 7, 1, 9, 0]
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
_onViewportChange = viewport => this.setState({viewport});
|
||||
|
||||
_getMap = () => {
|
||||
return this._mapRef.current ? this._mapRef.current.getMap() : null;
|
||||
};
|
||||
|
||||
_handleMapLoaded = event => {
|
||||
const map = this._getMap();
|
||||
|
||||
componentDidMount() {
|
||||
requestJson(
|
||||
'https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson',
|
||||
(error, response) => {
|
||||
@ -111,59 +59,56 @@ export default class App extends Component {
|
||||
const startTime = features[features.length - 1].properties.time;
|
||||
|
||||
this.setState({
|
||||
data: response,
|
||||
earthquakes: response,
|
||||
endTime,
|
||||
startTime,
|
||||
selectedTime: endTime
|
||||
});
|
||||
map.addSource(HEATMAP_SOURCE_ID, {type: 'geojson', data: response});
|
||||
map.addLayer(this._mkHeatmapLayer('heatmap-layer', HEATMAP_SOURCE_ID));
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
_onViewportChange = viewport => this.setState({viewport});
|
||||
|
||||
_handleChangeDay = time => {
|
||||
this.setState({selectedTime: time});
|
||||
if (this.state.earthquakes !== null && this.state.earthquakes.features) {
|
||||
const features = this._filterFeaturesByDay(this.state.earthquakes.features, time);
|
||||
this._setMapData(features);
|
||||
if (this.state.earthquakes) {
|
||||
this.setState({data: filterFeaturesByDay(this.state.earthquakes, time)});
|
||||
}
|
||||
};
|
||||
|
||||
_handleChangeAllDay = allDay => {
|
||||
this.setState({allDay});
|
||||
if (this.state.earthquakes !== null && this.state.earthquakes.features) {
|
||||
this._setMapData(
|
||||
allDay
|
||||
? this.state.earthquakes.features
|
||||
: this._filterFeaturesByDay(this.state.earthquakes.features, this.state.selectedTime)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
_setMapData = features => {
|
||||
const map = this._getMap();
|
||||
if (map) {
|
||||
map.getSource(HEATMAP_SOURCE_ID).setData(this._mkFeatureCollection(features));
|
||||
if (this.state.earthquakes) {
|
||||
this.setState({
|
||||
data: allDay
|
||||
? this.state.earthquakes
|
||||
: filterFeaturesByDay(this.state.earthquakes, this.state.selectedTime)
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {viewport, allDay, selectedTime, startTime, endTime} = this.state;
|
||||
const {viewport, data, allDay, selectedTime, startTime, endTime} = this.state;
|
||||
|
||||
return (
|
||||
<div style={{height: '100%'}}>
|
||||
<MapGL
|
||||
ref={this._mapRef}
|
||||
{...viewport}
|
||||
width="100%"
|
||||
height="100%"
|
||||
mapStyle="mapbox://styles/mapbox/dark-v9"
|
||||
onViewportChange={this._onViewportChange}
|
||||
mapboxApiAccessToken={MAPBOX_TOKEN}
|
||||
onLoad={this._handleMapLoaded}
|
||||
/>
|
||||
>
|
||||
{data && (
|
||||
<Source type="geojson" data={data}>
|
||||
<Layer {...heatmapLayer} />
|
||||
</Source>
|
||||
)}
|
||||
</MapGL>
|
||||
<ControlPanel
|
||||
containerComponent={this.props.containerComponent}
|
||||
startTime={startTime}
|
||||
|
||||
37
examples/heatmap/src/map-style.js
Normal file
37
examples/heatmap/src/map-style.js
Normal file
@ -0,0 +1,37 @@
|
||||
const MAX_ZOOM_LEVEL = 9;
|
||||
|
||||
export const heatmapLayer = {
|
||||
maxzoom: MAX_ZOOM_LEVEL,
|
||||
type: 'heatmap',
|
||||
paint: {
|
||||
// Increase the heatmap weight based on frequency and property magnitude
|
||||
'heatmap-weight': ['interpolate', ['linear'], ['get', 'mag'], 0, 0, 6, 1],
|
||||
// Increase the heatmap color weight weight by zoom level
|
||||
// heatmap-intensity is a multiplier on top of heatmap-weight
|
||||
'heatmap-intensity': ['interpolate', ['linear'], ['zoom'], 0, 1, MAX_ZOOM_LEVEL, 3],
|
||||
// Color ramp for heatmap. Domain is 0 (low) to 1 (high).
|
||||
// Begin color ramp at 0-stop with a 0-transparancy color
|
||||
// to create a blur-like effect.
|
||||
'heatmap-color': [
|
||||
'interpolate',
|
||||
['linear'],
|
||||
['heatmap-density'],
|
||||
0,
|
||||
'rgba(33,102,172,0)',
|
||||
0.2,
|
||||
'rgb(103,169,207)',
|
||||
0.4,
|
||||
'rgb(209,229,240)',
|
||||
0.6,
|
||||
'rgb(253,219,199)',
|
||||
0.8,
|
||||
'rgb(239,138,98)',
|
||||
0.9,
|
||||
'rgb(255,201,101)'
|
||||
],
|
||||
// Adjust the heatmap radius by zoom level
|
||||
'heatmap-radius': ['interpolate', ['linear'], ['zoom'], 0, 2, MAX_ZOOM_LEVEL, 20],
|
||||
// Transition from heatmap to circle layer by zoom level
|
||||
'heatmap-opacity': ['interpolate', ['linear'], ['zoom'], 7, 1, 9, 0]
|
||||
}
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user