maputnik/src/components/map/MapboxGlMap.jsx

151 lines
4.1 KiB
React
Raw Normal View History

import React from 'react'
2016-12-24 15:24:22 +01:00
import ReactDOM from 'react-dom'
import MapboxGl from 'mapbox-gl/dist/mapbox-gl.js'
2017-01-08 22:03:21 +01:00
import MapboxInspect from 'mapbox-gl-inspect'
2017-01-09 23:04:08 +01:00
import FeatureLayerPopup from './FeatureLayerPopup'
2017-01-08 22:03:21 +01:00
import FeaturePropertyPopup from './FeaturePropertyPopup'
import validateColor from 'mapbox-gl-style-spec/lib/validate/validate_color'
2016-12-20 11:44:22 +01:00
import style from '../../libs/style.js'
import tokens from '../../config/tokens.json'
2017-01-08 23:19:21 +01:00
import { colorHighlightedLayer } from '../../libs/highlight'
2016-12-24 15:14:31 +01:00
import 'mapbox-gl/dist/mapbox-gl.css'
2016-12-25 17:46:18 +01:00
import '../../mapboxgl.css'
2016-12-20 11:44:22 +01:00
2017-01-08 22:03:21 +01:00
function renderLayerPopup(features) {
2016-12-24 15:24:22 +01:00
var mountNode = document.createElement('div');
2017-01-09 23:04:08 +01:00
ReactDOM.render(<FeatureLayerPopup features={features} />, mountNode)
2016-12-24 15:24:22 +01:00
return mountNode.innerHTML;
}
2017-01-08 22:03:21 +01:00
function renderPropertyPopup(features) {
var mountNode = document.createElement('div');
ReactDOM.render(<FeaturePropertyPopup features={features} />, mountNode)
return mountNode.innerHTML;
}
2017-01-08 23:19:21 +01:00
function buildInspectStyle(originalMapStyle, coloredLayers, highlightedLayer) {
const backgroundLayer = {
"id": "background",
"type": "background",
"paint": {
2017-01-11 14:11:45 +01:00
"background-color": '#1c1f24',
2017-01-08 23:19:21 +01:00
}
}
const layer = colorHighlightedLayer(highlightedLayer)
if(layer) {
coloredLayers.push(layer)
}
2017-01-10 19:14:14 +01:00
const sources = {}
Object.keys(originalMapStyle.sources).forEach(sourceId => {
const source = originalMapStyle.sources[sourceId]
if(source.type !== 'raster') {
sources[sourceId] = source
}
})
2017-01-08 23:19:21 +01:00
const inspectStyle = {
...originalMapStyle,
2017-01-10 19:14:14 +01:00
sources: sources,
2017-01-08 23:19:21 +01:00
layers: [backgroundLayer].concat(coloredLayers)
}
return inspectStyle
}
2016-12-24 14:42:57 +01:00
export default class MapboxGlMap extends React.Component {
2016-12-19 21:21:10 +01:00
static propTypes = {
2016-12-24 14:42:57 +01:00
onDataChange: React.PropTypes.func,
mapStyle: React.PropTypes.object.isRequired,
2017-01-08 22:03:21 +01:00
inspectModeEnabled: React.PropTypes.bool.isRequired,
2017-01-08 23:19:21 +01:00
highlightedLayer: React.PropTypes.object,
2016-12-19 21:21:10 +01:00
}
static defaultProps = {
2016-12-24 14:42:57 +01:00
onMapLoaded: () => {},
onDataChange: () => {},
mapboxAccessToken: tokens.mapbox,
2016-12-19 21:21:10 +01:00
}
2016-12-19 14:52:04 +01:00
constructor(props) {
super(props)
MapboxGl.accessToken = tokens.mapbox
2016-12-24 17:24:24 +01:00
this.state = {
map: null,
inspect: null,
2016-12-24 17:24:24 +01:00
isPopupOpen: false,
popupX: 0,
popupY: 0,
}
2016-12-19 14:52:04 +01:00
}
2016-12-24 14:42:57 +01:00
componentWillReceiveProps(nextProps) {
2016-12-20 13:28:50 +01:00
if(!this.state.map) return
const metadata = nextProps.mapStyle.metadata || {}
MapboxGl.accessToken = metadata['maputnik:mapbox_access_token'] || tokens.mapbox
if(!nextProps.inspectModeEnabled) {
2017-01-08 22:03:21 +01:00
//Mapbox GL now does diffing natively so we don't need to calculate
//the necessary operations ourselves!
this.state.map.setStyle(nextProps.mapStyle, { diff: true})
}
}
2017-01-08 23:19:21 +01:00
componentDidUpdate(prevProps) {
if(this.props.inspectModeEnabled !== prevProps.inspectModeEnabled) {
this.state.inspect.toggleInspector()
}
if(this.props.inspectModeEnabled) {
2017-01-09 00:08:50 +01:00
this.state.inspect.render()
2017-01-08 23:19:21 +01:00
}
}
componentDidMount() {
const map = new MapboxGl.Map({
container: this.container,
2016-12-20 16:08:49 +01:00
style: this.props.mapStyle,
2016-12-24 15:17:15 +01:00
hash: true,
2016-12-24 14:42:57 +01:00
})
const nav = new MapboxGl.NavigationControl();
map.addControl(nav, 'top-right');
2016-12-24 15:14:31 +01:00
const inspect = new MapboxInspect({
2017-01-08 22:03:21 +01:00
popup: new MapboxGl.Popup({
closeOnClick: false
}),
2017-01-08 22:44:25 +01:00
showMapPopup: true,
showMapPopupOnHover: false,
showInspectMapPopupOnHover: true,
2017-01-08 22:03:21 +01:00
showInspectButton: false,
2017-01-08 23:19:21 +01:00
buildInspectStyle: (originalMapStyle, coloredLayers) => buildInspectStyle(originalMapStyle, coloredLayers, this.props.highlightedLayer),
2017-01-08 22:03:21 +01:00
renderPopup: features => {
if(this.props.inspectModeEnabled) {
return renderPropertyPopup(features)
} else {
return renderLayerPopup(features)
}
}
})
map.addControl(inspect)
2017-01-08 22:03:21 +01:00
2016-12-24 14:42:57 +01:00
map.on("style.load", () => {
this.setState({ map, inspect });
2016-12-24 14:42:57 +01:00
})
map.on("data", e => {
if(e.dataType !== 'tile') return
this.props.onDataChange({
map: this.state.map
})
})
}
render() {
return <div
2017-01-10 21:28:30 +01:00
className="maputnik-map"
2016-12-24 17:24:24 +01:00
ref={x => this.container = x}
2017-01-10 21:28:30 +01:00
></div>
}
}