diff --git a/src/components/App.jsx b/src/components/App.jsx index e816eaa0..47f57b16 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -212,6 +212,13 @@ export default class App extends React.Component { vectorLayers: {}, mapState: "map", spec: latest, + mapView: { + zoom: 0, + center: { + lng: 0, + lat: 0, + }, + }, isOpen: { settings: false, sources: false, @@ -531,11 +538,22 @@ export default class App extends React.Component { return metadata['maputnik:renderer'] || 'mbgljs'; } + onMapChange = (mapView) => { + this.setState({ + mapView, + }); + } + mapRenderer() { const metadata = this.state.mapStyle.metadata || {}; const mapProps = { - mapStyle: style.replaceAccessTokens(this.state.mapStyle, {allowFallback: true}), + mapStyle: this.state.mapStyle, + replaceAccessTokens: (mapStyle) => { + return style.replaceAccessTokens(mapStyle, { + allowFallback: true + }); + }, onDataChange: (e) => { this.layerWatcher.analyzeMap(e.map) this.fetchSources(); @@ -550,11 +568,13 @@ export default class App extends React.Component { if(renderer === 'ol') { mapElement = } else { mapElement = this.shortcutEl = el} diff --git a/src/components/map/MapboxGlMap.jsx b/src/components/map/MapboxGlMap.jsx index 794dbc79..3b04702c 100644 --- a/src/components/map/MapboxGlMap.jsx +++ b/src/components/map/MapboxGlMap.jsx @@ -60,12 +60,15 @@ export default class MapboxGlMap extends React.Component { inspectModeEnabled: PropTypes.bool.isRequired, highlightedLayer: PropTypes.object, options: PropTypes.object, + replaceAccessTokens: PropTypes.func.isRequired, + onChange: PropTypes.func.isRequired, } static defaultProps = { onMapLoaded: () => {}, onDataChange: () => {}, onLayerSelect: () => {}, + onChange: () => {}, mapboxAccessToken: tokens.mapbox, options: {}, } @@ -88,7 +91,10 @@ export default class MapboxGlMap extends React.Component { //Mapbox GL now does diffing natively so we don't need to calculate //the necessary operations ourselves! - this.state.map.setStyle(props.mapStyle, {diff: true}) + this.state.map.setStyle( + this.props.replaceAccessTokens(props.mapStyle), + {diff: true} + ) } componentDidUpdate(prevProps) { @@ -128,12 +134,19 @@ export default class MapboxGlMap extends React.Component { const map = new MapboxGl.Map(mapOpts); + const mapViewChange = () => { + const center = map.getCenter(); + const zoom = map.getZoom(); + this.props.onChange({center, zoom}); + } + mapViewChange(); + map.showTileBoundaries = mapOpts.showTileBoundaries; map.showCollisionBoxes = mapOpts.showCollisionBoxes; map.showOverdrawInspector = mapOpts.showOverdrawInspector; - const zoom = new ZoomControl; - map.addControl(zoom, 'top-right'); + const zoomControl = new ZoomControl; + map.addControl(zoomControl, 'top-right'); const nav = new MapboxGl.NavigationControl({visualizePitch:true}); map.addControl(nav, 'top-right'); @@ -189,7 +202,10 @@ export default class MapboxGlMap extends React.Component { this.setState({ zoom: map.getZoom() }); - }) + }); + + map.on("dragend", mapViewChange); + map.on("zoomend", mapViewChange); } render() { diff --git a/src/components/map/OpenLayersMap.jsx b/src/components/map/OpenLayersMap.jsx index b1ee83a7..446096a5 100644 --- a/src/components/map/OpenLayersMap.jsx +++ b/src/components/map/OpenLayersMap.jsx @@ -32,6 +32,8 @@ export default class OpenLayersMap extends React.Component { style: PropTypes.object, onLayerSelect: PropTypes.func.isRequired, debugToolbox: PropTypes.bool.isRequired, + replaceAccessTokens: PropTypes.func.isRequired, + onChange: PropTypes.func.isRequired, } static defaultProps = { @@ -61,7 +63,9 @@ export default class OpenLayersMap extends React.Component { componentDidUpdate(prevProps) { if (this.props.mapStyle !== prevProps.mapStyle) { - this.updateStyle(this.props.mapStyle); + this.updateStyle( + this.props.replaceAccessTokens(this.props.mapStyle) + ); } } @@ -93,6 +97,22 @@ export default class OpenLayersMap extends React.Component { }) }) + const onMoveEnd = () => { + const zoom = map.getView().getZoom(); + const center = toLonLat(map.getView().getCenter()); + + this.props.onChange({ + zoom, + center: { + lng: center[0], + lat: center[1], + }, + }); + } + + onMoveEnd(); + map.on('moveend', onMoveEnd); + map.on('postrender', (evt) => { const center = toLonLat(map.getView().getCenter()); this.setState({ @@ -108,7 +128,9 @@ export default class OpenLayersMap extends React.Component { this.map = map; - this.updateStyle(this.props.mapStyle); + this.updateStyle( + this.props.replaceAccessTokens(this.props.mapStyle) + ); } closeOverlay = (e) => { diff --git a/src/components/modals/DebugModal.js b/src/components/modals/DebugModal.js index 91bf47c7..181983f1 100644 --- a/src/components/modals/DebugModal.js +++ b/src/components/modals/DebugModal.js @@ -13,9 +13,16 @@ class DebugModal extends React.Component { onOpenToggle: PropTypes.func.isRequired, mapboxGlDebugOptions: PropTypes.object, openlayersDebugOptions: PropTypes.object, + mapView: PropTypes.object, } render() { + const {mapView} = this.props; + + const osmZoom = Math.round(mapView.zoom)+1; + const osmLon = Number.parseFloat(mapView.center.lng).toFixed(5); + const osmLat = Number.parseFloat(mapView.center.lat).toFixed(5); + return
+

Options

{this.props.renderer === 'mbgljs' &&
    {Object.entries(this.props.mapboxGlDebugOptions).map(([key, val]) => { @@ -46,6 +54,18 @@ class DebugModal extends React.Component {
}
+
+

Links

+

+ + Open in OSM + — Opens the current view on openstreetmap.org +

+
} }