mirror of
https://github.com/a-nyx/maputnik-with-pmtiles.git
synced 2024-12-27 09:15:29 +01:00
Load OL3 code only once we need it
This commit is contained in:
parent
607e920548
commit
3ee1473a49
8 changed files with 123 additions and 46 deletions
|
@ -110,8 +110,10 @@ export default class App extends React.Component {
|
|||
|
||||
const metadata = this.state.mapStyle.metadata || {}
|
||||
const renderer = metadata['maputnik:renderer'] || 'mbgljs'
|
||||
|
||||
// Check if OL3 code has been loaded?
|
||||
if(renderer === 'ol3') {
|
||||
return <OpenLayers3Map {...mapProps} />
|
||||
return <OpenLayers3Map {...mapProps} />
|
||||
} else {
|
||||
return <MapboxGlMap {...mapProps} />
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ class StringInput extends React.Component {
|
|||
static propTypes = {
|
||||
value: React.PropTypes.string,
|
||||
style: React.PropTypes.object,
|
||||
onChange: React.PropTypes.func.isRequired,
|
||||
onChange: React.PropTypes.func,
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
@ -1,38 +1,61 @@
|
|||
import React from 'react'
|
||||
import ol from 'openlayers'
|
||||
import olms from 'ol-mapbox-style'
|
||||
|
||||
import Map from './Map'
|
||||
import style from '../../libs/style.js'
|
||||
|
||||
export default class OpenLayers3Map extends Map {
|
||||
class OpenLayers3Map extends Map {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
const tilegrid = ol.tilegrid.createXYZ({tileSize: 512, maxZoom: 22})
|
||||
this.resolutions = tilegrid.getResolutions()
|
||||
this.layer = new ol.layer.VectorTile({
|
||||
source: new ol.source.VectorTile({
|
||||
attributions: '© <a href="https://www.mapbox.com/map-feedback/">Mapbox</a> ' +
|
||||
'© <a href="http://www.openstreetmap.org/copyright">' +
|
||||
'OpenStreetMap contributors</a>',
|
||||
format: new ol.format.MVT(),
|
||||
tileGrid: tilegrid,
|
||||
tilePixelRatio: 8,
|
||||
url: 'http://osm2vectortiles-0.tileserver.com/v2/{z}/{x}/{y}.pbf'
|
||||
this.state = {
|
||||
map: null,
|
||||
ol: null,
|
||||
olms: null
|
||||
}
|
||||
|
||||
//Load OpenLayers dynamically once we need it
|
||||
//TODO: Make this more convenient
|
||||
require.ensure(["openlayers", "ol-mapbox-style"], ()=> {
|
||||
const ol = require('openlayers')
|
||||
const olms = require('ol-mapbox-style')
|
||||
|
||||
const tilegrid = ol.tilegrid.createXYZ({tileSize: 512, maxZoom: 22})
|
||||
this.resolutions = tilegrid.getResolutions()
|
||||
this.layer = new ol.layer.VectorTile({
|
||||
source: new ol.source.VectorTile({
|
||||
attributions: '© <a href="https://www.mapbox.com/map-feedback/">Mapbox</a> ' +
|
||||
'© <a href="http://www.openstreetmap.org/copyright">' +
|
||||
'OpenStreetMap contributors</a>',
|
||||
format: new ol.format.MVT(),
|
||||
tileGrid: tilegrid,
|
||||
tilePixelRatio: 8,
|
||||
url: 'http://osm2vectortiles-0.tileserver.com/v2/{z}/{x}/{y}.pbf'
|
||||
})
|
||||
})
|
||||
|
||||
this.setState({
|
||||
ol: ol,
|
||||
olms: olms,
|
||||
})
|
||||
console.log('Loaded OpenLayers3 renderer')
|
||||
})
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const olms = this.state.olms
|
||||
const ol = this.state.ol
|
||||
if(!olms || !ol) return
|
||||
|
||||
const jsonStyle = style.toJSON(nextProps.mapStyle)
|
||||
const styleFunc = olms.getStyleFunction(jsonStyle, 'mapbox', this.resolutions)
|
||||
this.layer.setStyle(styleFunc)
|
||||
this.state.map.render()
|
||||
}
|
||||
|
||||
|
||||
componentDidMount() {
|
||||
const olms = this.state.olms
|
||||
const ol = this.state.ol
|
||||
if(!olms || !ol) return
|
||||
|
||||
const jsonStyle = style.toJSON(this.props.mapStyle)
|
||||
const styleFunc = olms.getStyleFunction(jsonStyle, 'mapbox', this.resolutions)
|
||||
this.layer.setStyle(styleFunc)
|
||||
|
@ -49,3 +72,5 @@ export default class OpenLayers3Map extends Map {
|
|||
this.setState({ map });
|
||||
}
|
||||
}
|
||||
|
||||
export default OpenLayers3Map
|
||||
|
|
|
@ -23,8 +23,14 @@ class SettingsModal extends React.Component {
|
|||
this.props.onStyleChanged(changedStyle)
|
||||
}
|
||||
|
||||
onRendererChange(e) {
|
||||
const changedStyle = this.props.mapStyle.setIn(['metadata', 'maputnik:renderer'], e.target.value)
|
||||
onRendererChange(renderer) {
|
||||
const changedStyle = {
|
||||
...this.props.mapStyle,
|
||||
metadata: {
|
||||
...this.props.mapStyle.metadata,
|
||||
'maputnik:renderer': renderer,
|
||||
}
|
||||
}
|
||||
this.props.onStyleChanged(changedStyle)
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import StringInput from '../inputs/StringInput'
|
|||
import SelectInput from '../inputs/SelectInput'
|
||||
import SourceTypeEditor from '../sources/SourceTypeEditor'
|
||||
|
||||
import style from '../../libs/style'
|
||||
import publicSources from '../../config/tilesets.json'
|
||||
import colors from '../../config/colors'
|
||||
import { margins, fontSizes } from '../../config/scales'
|
||||
|
@ -34,12 +35,15 @@ class PublicSource extends React.Component {
|
|||
fontSize: fontSizes[4],
|
||||
color: colors.lowgray,
|
||||
}}>
|
||||
<Button style={{
|
||||
backgroundColor: 'transparent',
|
||||
padding: margins[2],
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
}}>
|
||||
<Button
|
||||
onClick={() => this.props.onSelect(this.props.id)}
|
||||
style={{
|
||||
backgroundColor: 'transparent',
|
||||
padding: margins[2],
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<span style={{fontWeight: 700}}>{this.props.title}</span>
|
||||
<br/>
|
||||
|
@ -114,10 +118,21 @@ class AddSource extends React.Component {
|
|||
super(props)
|
||||
this.state = {
|
||||
mode: 'tilejson',
|
||||
source: {}
|
||||
source: {
|
||||
id: style.generateId(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onSourceIdChange(newId) {
|
||||
this.setState({
|
||||
source: {
|
||||
...this.state.source,
|
||||
id: newId,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onSourceChange(source) {
|
||||
this.setState({
|
||||
source: source
|
||||
|
@ -128,7 +143,8 @@ class AddSource extends React.Component {
|
|||
return <div>
|
||||
<InputBlock label={"Source ID"}>
|
||||
<StringInput
|
||||
value={'blubid'}
|
||||
value={this.state.source.id}
|
||||
onChange={this.onSourceIdChange.bind(this)}
|
||||
/>
|
||||
</InputBlock>
|
||||
<InputBlock label={"Source Type"}>
|
||||
|
@ -147,7 +163,7 @@ class AddSource extends React.Component {
|
|||
mode={this.state.mode}
|
||||
source={this.state.source}
|
||||
/>
|
||||
<Button onClick={() => this.props.onSourceAdd(this.state.source)}>
|
||||
<Button onClick={() => this.onSourceAdd(this.state.source)}>
|
||||
Add Source
|
||||
</Button>
|
||||
</div>
|
||||
|
@ -159,6 +175,21 @@ class SourcesModal extends React.Component {
|
|||
mapStyle: React.PropTypes.object.isRequired,
|
||||
isOpen: React.PropTypes.bool.isRequired,
|
||||
onOpenToggle: React.PropTypes.func.isRequired,
|
||||
onStyleChanged: React.PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
onSourceAdd(source) {
|
||||
const changedSources = {
|
||||
...this.props.mapStyle.sources,
|
||||
[source.id]: source
|
||||
}
|
||||
|
||||
const changedStyle = {
|
||||
...this.props.mapStyle,
|
||||
sources: changedSources
|
||||
}
|
||||
|
||||
this.props.onStyleChanged(changedStyle)
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -167,12 +198,14 @@ class SourcesModal extends React.Component {
|
|||
return <SourceEditorLayout sourceId={sourceId} source={source} />
|
||||
})
|
||||
|
||||
const tilesetOptions = publicSources.filter(tileset => !(tileset.id in this.props.mapStyle.sources)).map(tileset => {
|
||||
const tilesetOptions = publicSources.filter(source => !(source.id in this.props.mapStyle.sources)).map(source => {
|
||||
return <PublicSource
|
||||
id={tileset.id}
|
||||
type={tileset.type}
|
||||
title={tileset.title}
|
||||
description={tileset.description}
|
||||
key={source.id}
|
||||
id={source.id}
|
||||
type={source.type}
|
||||
title={source.title}
|
||||
description={source.description}
|
||||
onSelect={() => this.onSourceAdd(source)}
|
||||
/>
|
||||
})
|
||||
|
||||
|
@ -188,7 +221,7 @@ class SourcesModal extends React.Component {
|
|||
<Heading level={4}>Add New Source</Heading>
|
||||
<div style={{maxWidth: 300}}>
|
||||
<p style={{color: colors.lowgray, fontSize: fontSizes[5]}}>Add a new source to your style. You can only choose the source type and id at creation time!</p>
|
||||
<AddSource />
|
||||
<AddSource onSourceAdd={this.onSourceAdd.bind(this)} />
|
||||
</div>
|
||||
|
||||
<Heading level={4}>Choose Public Source</Heading>
|
||||
|
|
|
@ -5,7 +5,7 @@ import StringInput from '../inputs/StringInput'
|
|||
class TileJSONSourceEditor extends React.Component {
|
||||
static propTypes = {
|
||||
url: React.PropTypes.string.isRequired,
|
||||
onChange: React.PropTypes.func.isRequired,
|
||||
onChange: React.PropTypes.func,
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -23,7 +23,7 @@ class TileURLSourceEditor extends React.Component {
|
|||
tiles: React.PropTypes.array.isRequired,
|
||||
minZoom: React.PropTypes.number.isRequired,
|
||||
maxZoom: React.PropTypes.number.isRequired,
|
||||
onChange: React.PropTypes.func.isRequired,
|
||||
onChange: React.PropTypes.func,
|
||||
}
|
||||
|
||||
renderTileUrls() {
|
||||
|
@ -59,7 +59,7 @@ class TileURLSourceEditor extends React.Component {
|
|||
class GeoJSONSourceEditor extends React.Component {
|
||||
static propTypes = {
|
||||
data: React.PropTypes.string.isRequired,
|
||||
onChange: React.PropTypes.func.isRequired,
|
||||
onChange: React.PropTypes.func,
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
@ -8,9 +8,13 @@ const emptyStyle = ensureMetadataExists({
|
|||
layers: [],
|
||||
})
|
||||
|
||||
function generateId() {
|
||||
return Math.random().toString(36).substr(2, 9)
|
||||
}
|
||||
|
||||
function ensureHasId(style) {
|
||||
if('id' in style) return style
|
||||
style.id = Math.random().toString(36).substr(2, 9)
|
||||
style.id = generateId()
|
||||
return style
|
||||
}
|
||||
|
||||
|
@ -37,4 +41,5 @@ export default {
|
|||
ensureMetadataExists,
|
||||
emptyStyle,
|
||||
indexOfLayer,
|
||||
generateId,
|
||||
}
|
||||
|
|
|
@ -28,26 +28,32 @@ module.exports = {
|
|||
app: './src/index.jsx',
|
||||
vendor: [
|
||||
'file-saver',
|
||||
'immutable',
|
||||
'mapbox-gl',
|
||||
//TODO: Cannot resolve migrations file?
|
||||
//TODO: Build failure because cannot resolve migrations file
|
||||
//"mapbox-gl-style-spec",
|
||||
"radium",
|
||||
"randomcolor",
|
||||
"lodash.clonedeep",
|
||||
"lodash.throttle",
|
||||
"lodash.topairs",
|
||||
'color',
|
||||
'react',
|
||||
"react-dom",
|
||||
"react-color",
|
||||
"react-file-reader-input",
|
||||
"react-collapse",
|
||||
"react-height",
|
||||
"react-icon-base",
|
||||
"react-motion",
|
||||
"react-sortable-hoc",
|
||||
"request",
|
||||
//TODO: Icons raise multi vendor errors?
|
||||
//"react-icons",
|
||||
// Open Layers
|
||||
'openlayers',
|
||||
'ol-mapbox-style'
|
||||
]
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, 'public'),
|
||||
filename: '[chunkhash].app.js'
|
||||
filename: '[name].[chunkhash].js',
|
||||
chunkFilename: '[chunkhash].js'
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
|
|
Loading…
Reference in a new issue