Use first vector source for OL3

This commit is contained in:
Lukas Martinelli 2017-01-10 14:05:25 +01:00
parent 7ff0ac9bb5
commit b470885263
3 changed files with 80 additions and 43 deletions

View file

@ -1,5 +1,32 @@
import React from 'react' import React from 'react'
import style from '../../libs/style.js' import style from '../../libs/style.js'
import isEqual from 'lodash.isequal'
function suitableVectorSource(mapStyle) {
const sources = Object.keys(mapStyle.sources)
.map(sourceId => {
return {
id: sourceId,
source: mapStyle.sources[sourceId]
}
})
.filter(({source}) => source.type === 'vector' && source.tiles && source.tiles.length > 0)
.filter(({source}) => source.tiles.length > 0)
return sources[0]
}
function toVectorLayer(source, tilegrid) {
const ol = require('openlayers')
return new ol.layer.VectorTile({
source: new ol.source.VectorTile({
format: new ol.format.MVT(),
tileGrid: tilegrid,
tilePixelRatio: 8,
url: source.tiles[0]
})
})
}
class OpenLayers3Map extends React.Component { class OpenLayers3Map extends React.Component {
static propTypes = { static propTypes = {
@ -13,20 +40,41 @@ class OpenLayers3Map extends React.Component {
onDataChange: () => {}, onDataChange: () => {},
} }
constructor(props) {
super(props)
this.tilegrid = null
this.resolutions = null
this.layer = null
this.map = null
}
updateStyle(newMapStyle) {
const oldSource = suitableVectorSource(this.props.mapStyle)
const newSource = suitableVectorSource(newMapStyle)
if(newSource) {
if(!this.layer) {
this.layer = toVectorLayer(newSource.source, this.tilegrid)
this.map.addLayer(this.layer)
} else if(!isEqual(oldSource, newSource)) {
this.map.removeLayer(this.layer)
this.layer = toVectorLayer(newSource.source, this.tilegrid)
this.map.addLayer(this.layer)
}
const olms = require('ol-mapbox-style')
const styleFunc = olms.getStyleFunction(newMapStyle, newSource.id, this.resolutions)
this.layer.setStyle(styleFunc)
//NOTE: We need to mark the source as changed in order
//to trigger a rerender
this.layer.getSource().changed()
this.map.render()
}
}
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
require.ensure(["openlayers", "ol-mapbox-style"], ()=> { require.ensure(["openlayers", "ol-mapbox-style"], () => {
const ol = require('openlayers') if(!this.map || !this.resolutions) return
const olms = require('ol-mapbox-style') this.updateStyle(nextProps.mapStyle)
const jsonStyle = nextProps.mapStyle
const styleFunc = olms.getStyleFunction(jsonStyle, 'openmaptiles', this.resolutions)
const layer = this.layer
layer.setStyle(styleFunc)
//NOTE: We need to mark the source as changed in order
//to trigger a rerender
layer.getSource().changed()
this.state.map.render()
}) })
} }
@ -39,46 +87,36 @@ class OpenLayers3Map extends React.Component {
const ol = require('openlayers') const ol = require('openlayers')
const olms = require('ol-mapbox-style') const olms = require('ol-mapbox-style')
const tilegrid = ol.tilegrid.createXYZ({tileSize: 512, maxZoom: 22}) this.tilegrid = ol.tilegrid.createXYZ({tileSize: 512, maxZoom: 22})
this.resolutions = tilegrid.getResolutions() this.resolutions = this.tilegrid.getResolutions()
this.layer = new ol.layer.VectorTile({
source: new ol.source.VectorTile({
attributions: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap contributors</a>',
format: new ol.format.MVT(),
tileGrid: tilegrid,
tilePixelRatio: 8,
url: 'https://free-0.tilehosting.com/data/v3/{z}/{x}/{y}.pbf?key=tXiQqN3lIgskyDErJCeY'
})
})
const jsonStyle = this.props.mapStyle
const styleFunc = olms.getStyleFunction(jsonStyle, 'openmaptiles', this.resolutions)
this.layer.setStyle(styleFunc)
const map = new ol.Map({ const map = new ol.Map({
target: this.container, target: this.container,
layers: [this.layer], layers: [],
view: new ol.View({ view: new ol.View({
center: jsonStyle.center,
zoom: 2, zoom: 2,
//zoom: jsonStyle.zoom, center: [52.5, -78.4]
}) })
}) })
map.addControl(new ol.control.Zoom()); map.addControl(new ol.control.Zoom())
this.setState({ map }); this.map = map
this.updateStyle(this.props.mapStyle)
}) })
} }
render() { render() {
return <div return <div
ref={x => this.container = x} ref={x => this.container = x}
style={{ style={{
position: "fixed", position: "fixed",
top: 0, top: 0,
bottom: 0, right: 0,
height: "100%", bottom: 0,
width: "100%", height: "100%",
}}></div> width: "75%",
...this.props.style,
}}>
</div>
} }
} }

View file

@ -66,7 +66,7 @@ class AddModal extends React.Component {
if(!this.state.source && sourceIds.length > 0) { if(!this.state.source && sourceIds.length > 0) {
this.setState({ this.setState({
source: sourceIds[0], source: sourceIds[0],
'source-layer': this.state['source-layer'] || nextProps.sources[sourceIds[0]][0] 'source-layer': this.state['source-layer'] || (nextProps.sources[sourceIds[0]] || [])[0]
}) })
} }
} }

View file

@ -105,7 +105,6 @@ class ActiveSourceTypeEditor extends React.Component {
borderWidth: 2, borderWidth: 2,
borderStyle: 'solid', borderStyle: 'solid',
padding: margins[1], padding: margins[1],
height: 50
}}> }}>
<SourceTypeEditor <SourceTypeEditor
onChange={this.props.onChange} onChange={this.props.onChange}