mirror of
https://github.com/a-nyx/maputnik-with-pmtiles.git
synced 2024-12-27 09:05:25 +01:00
Implement style loading and passing to map component
This commit is contained in:
parent
392a7aa832
commit
7f9fb4579e
13 changed files with 84 additions and 143 deletions
|
@ -17,12 +17,14 @@
|
||||||
"homepage": "https://github.com/lukasmartinelli/mapolo#readme",
|
"homepage": "https://github.com/lukasmartinelli/mapolo#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mapbox-gl": "^0.23.0",
|
"mapbox-gl": "^0.23.0",
|
||||||
|
"mapbox-gl-style-spec": "^8.8.0",
|
||||||
"node-sass": "^3.9.2",
|
"node-sass": "^3.9.2",
|
||||||
"react": "15.3.0",
|
"react": "15.3.0",
|
||||||
"react-dom": "15.3.0",
|
"react-dom": "15.3.0",
|
||||||
"react-file-reader-input": "^1.1.0",
|
"react-file-reader-input": "^1.1.0",
|
||||||
"react-geomicons": "^2.0.5",
|
"react-geomicons": "^2.0.5",
|
||||||
"react-icons": "^2.2.1",
|
"react-icons": "^2.2.1",
|
||||||
|
"react-mapbox-gl": "^0.11.0",
|
||||||
"react-tap-event-plugin": "^1.0.0",
|
"react-tap-event-plugin": "^1.0.0",
|
||||||
"rebass": "^0.3.1",
|
"rebass": "^0.3.1",
|
||||||
"sass-loader": "^4.0.1"
|
"sass-loader": "^4.0.1"
|
||||||
|
|
52
src/app.jsx
52
src/app.jsx
|
@ -1,14 +1,21 @@
|
||||||
import {Workspace} from './workspace.jsx';
|
import React from 'react'
|
||||||
import {Map} from './map.jsx';
|
|
||||||
import {Toolbar} from './toolbar.jsx';
|
|
||||||
import React from 'react';
|
|
||||||
import styles from './layout.scss';
|
|
||||||
import { Drawer, Container, Block, Fixed } from 'rebass'
|
import { Drawer, Container, Block, Fixed } from 'rebass'
|
||||||
|
import {Map} from './map.jsx'
|
||||||
|
import {Toolbar} from './toolbar.jsx'
|
||||||
import { LayerEditor } from './layers.jsx'
|
import { LayerEditor } from './layers.jsx'
|
||||||
import theme from './theme.jsx'
|
|
||||||
|
import theme from './theme.js'
|
||||||
|
import layout from './layout.scss'
|
||||||
|
|
||||||
export class WorkspaceDrawer extends React.Component {
|
export class WorkspaceDrawer extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
|
let editor = null
|
||||||
|
|
||||||
|
if(this.props.mapStyle) {
|
||||||
|
editor = <LayerEditor layers={this.props.mapStyle.layers}/>
|
||||||
|
}
|
||||||
|
|
||||||
return <Container style={{
|
return <Container style={{
|
||||||
zIndex: 100,
|
zIndex: 100,
|
||||||
position: "fixed",
|
position: "fixed",
|
||||||
|
@ -19,8 +26,8 @@ export class WorkspaceDrawer extends React.Component {
|
||||||
bottom: "0",
|
bottom: "0",
|
||||||
backgroundColor: theme.colors.gray}
|
backgroundColor: theme.colors.gray}
|
||||||
} >
|
} >
|
||||||
<LayerEditor />
|
{editor}
|
||||||
</Container>;
|
</Container>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +37,18 @@ export default class App extends React.Component {
|
||||||
reactIconBase: React.PropTypes.object
|
reactIconBase: React.PropTypes.object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
this.updateStyle = this.updateStyle.bind(this);
|
||||||
|
this.state = {
|
||||||
|
mapStyle: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateStyle(newStyle) {
|
||||||
|
this.setState({ mapStyle: newStyle })
|
||||||
|
}
|
||||||
|
|
||||||
getChildContext () {
|
getChildContext () {
|
||||||
return {
|
return {
|
||||||
rebass: theme,
|
rebass: theme,
|
||||||
|
@ -40,14 +59,13 @@ export default class App extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
console.log(this.state.mapStyle)
|
||||||
<div>
|
return <div>
|
||||||
<Toolbar />
|
<Toolbar onStyleUpload={this.updateStyle} />
|
||||||
<WorkspaceDrawer />
|
<WorkspaceDrawer mapStyle={this.state.mapStyle} />
|
||||||
<div className={styles.layoutMap}>
|
<div className={layout.map}>
|
||||||
<Map />
|
<Map mapStyle={this.state.mapStyle} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import styles from './button.scss';
|
|
||||||
import { Button, Text } from 'rebass'
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
.button {
|
|
||||||
text-align: center;
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0px;
|
|
||||||
padding: 10px;
|
|
||||||
position: relative;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 3px;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
font-family: 'Open Sans Bold', sans-serif;
|
|
||||||
line-height: 20px;
|
|
||||||
font-size: 12px;
|
|
||||||
|
|
||||||
color: #fff;
|
|
||||||
background-color: rgba(255,255,255,0.10);
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
.blueBg {
|
|
||||||
background-color: blue;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
|
@ -1,17 +1,23 @@
|
||||||
import React from 'react';
|
import React from 'react'
|
||||||
|
|
||||||
import { Toolbar, NavItem, Tooltip, Container, Space} from 'rebass'
|
import { Toolbar, NavItem, Tooltip, Container, Space} from 'rebass'
|
||||||
import theme from './theme.jsx';
|
import { Button, Text } from 'rebass'
|
||||||
import { Button, Text } from 'rebass';
|
|
||||||
|
import theme from './theme.js'
|
||||||
|
|
||||||
export class LayerEditor extends React.Component {
|
export class LayerEditor extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
|
const layerBlocks = this.props.layers.map(layer => {
|
||||||
|
console.log(layer)
|
||||||
|
return <Text>{layer.id}</Text>
|
||||||
|
});
|
||||||
return <Container>
|
return <Container>
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<NavItem is="a">
|
<NavItem is="a">
|
||||||
Toolbar
|
Toolbar
|
||||||
</NavItem>
|
</NavItem>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</Container>;
|
{layerBlocks}
|
||||||
|
</Container>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layoutMap {
|
.map {
|
||||||
@include full-height;
|
@include full-height;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
|
21
src/map.jsx
21
src/map.jsx
|
@ -1,21 +1,18 @@
|
||||||
import React from 'react';
|
import React from 'react'
|
||||||
import MapboxGl from 'mapbox-gl';
|
import ReactMapboxGl from "react-mapbox-gl"
|
||||||
|
|
||||||
export class Map extends React.Component {
|
export class Map extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props)
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
MapboxGl.accessToken = "pk.eyJ1IjoibW9yZ2Vua2FmZmVlIiwiYSI6IjIzcmN0NlkifQ.0LRTNgCc-envt9d5MzR75w";
|
|
||||||
const map = new MapboxGl.Map({
|
|
||||||
container: this.container,
|
|
||||||
style: "mapbox://styles/morgenkaffee/cirqasdb8003dh1ntbo6dkvs6"
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <div ref={x => this.container = x} style={{zIndex: 15}}></div>
|
if (this.props.mapStyle) {
|
||||||
|
return <ReactMapboxGl
|
||||||
|
style={this.props.mapStyle}
|
||||||
|
accessToken="pk.eyJ1IjoibW9yZ2Vua2FmZmVlIiwiYSI6IjIzcmN0NlkifQ.0LRTNgCc-envt9d5MzR75w"/>
|
||||||
|
}
|
||||||
|
return <div />
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
36
src/style.js
36
src/style.js
|
@ -1,27 +1,27 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
export class StyleCommand {
|
// A wrapper around Mapbox GL style
|
||||||
do(map) {
|
export class Style {
|
||||||
throw new TypeError("Do not implemented");
|
constructor() {
|
||||||
|
this.styleHistory = [];
|
||||||
|
this.renderers = [];
|
||||||
}
|
}
|
||||||
undo(map) {
|
|
||||||
throw new TypeError("Undo not implemented");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class StyleEditor {
|
load(style) {
|
||||||
constructor(map, style) {
|
this.currentStyle = style;
|
||||||
this.map = map;
|
}
|
||||||
this.style = style;
|
|
||||||
this.history = [];
|
onRender(cb) {
|
||||||
|
this.renderers.push(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(style) {
|
||||||
|
this.styleHistory.push(this.currentStyle);
|
||||||
|
this.currentStyle = style;
|
||||||
|
this.renderers.forEach(r => r(this.currentStyle))
|
||||||
}
|
}
|
||||||
|
|
||||||
layers() {
|
layers() {
|
||||||
return this.style.layers;
|
return this.currentStyle.layers;
|
||||||
}
|
|
||||||
|
|
||||||
execute(command) {
|
|
||||||
this.history.push(command);
|
|
||||||
command.do(this.map);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { Menu, NavItem, Tooltip, Container, Block, Fixed } from 'rebass'
|
|
||||||
import theme from './theme.jsx';
|
|
||||||
import {MdSettings, MdPalette, MdLayers, MdSave, MdFolderOpen} from 'react-icons/lib/md';
|
|
||||||
import { Button, Text } from 'rebass';
|
|
||||||
import FileReaderInput from 'react-file-reader-input';
|
import FileReaderInput from 'react-file-reader-input';
|
||||||
|
|
||||||
|
import { Button, Text } from 'rebass';
|
||||||
|
import { Menu, NavItem, Tooltip, Container, Block, Fixed } from 'rebass'
|
||||||
|
import {MdSettings, MdPalette, MdLayers, MdSave, MdFolderOpen} from 'react-icons/lib/md';
|
||||||
|
|
||||||
|
import theme from './theme.js';
|
||||||
|
|
||||||
export class Toolbar extends React.Component {
|
export class Toolbar extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.onUpload = this.onUpload.bind(this);
|
||||||
styleFile: null
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onUpload(_, files) {
|
onUpload(_, files) {
|
||||||
|
@ -20,10 +19,11 @@ export class Toolbar extends React.Component {
|
||||||
reader.readAsText(file, "UTF-8");
|
reader.readAsText(file, "UTF-8");
|
||||||
reader.onload = e => {
|
reader.onload = e => {
|
||||||
const style = JSON.parse(e.target.result);
|
const style = JSON.parse(e.target.result);
|
||||||
console.log(style);
|
this.props.onStyleUpload(style);
|
||||||
}
|
}
|
||||||
reader.onerror = e => console.log(e.target);
|
reader.onerror = e => console.log(e.target);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <Container style={{
|
return <Container style={{
|
||||||
zIndex: 100,
|
zIndex: 100,
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { Space, Toolbar, ButtonCircle, Text, Panel, PanelHeader, PanelFooter } from 'rebass'
|
|
||||||
import Icon from 'react-geomicons';
|
|
||||||
|
|
||||||
|
|
||||||
export class Workspace extends React.Component {
|
|
||||||
render() {
|
|
||||||
return <div className="workspace">
|
|
||||||
<Toolbar>
|
|
||||||
<Text>Hey layer</Text>
|
|
||||||
<Space
|
|
||||||
auto
|
|
||||||
x={1}
|
|
||||||
/>
|
|
||||||
<ButtonCircle title="Like">
|
|
||||||
<Icon
|
|
||||||
fill="currentColor"
|
|
||||||
height="1em"
|
|
||||||
name="no"
|
|
||||||
width="1em"
|
|
||||||
/>
|
|
||||||
</ButtonCircle>
|
|
||||||
<ButtonCircle title="Like">
|
|
||||||
<Icon
|
|
||||||
fill="currentColor"
|
|
||||||
height="1em"
|
|
||||||
name="trash"
|
|
||||||
width="1em"
|
|
||||||
/>
|
|
||||||
</ButtonCircle>
|
|
||||||
<ButtonCircle title="Like">
|
|
||||||
<Icon
|
|
||||||
fill="currentColor"
|
|
||||||
height="1em"
|
|
||||||
name="triangleUp"
|
|
||||||
width="1em"
|
|
||||||
/>
|
|
||||||
</ButtonCircle>
|
|
||||||
<ButtonCircle title="Like">
|
|
||||||
<Icon
|
|
||||||
fill="currentColor"
|
|
||||||
height="1em"
|
|
||||||
name="heart"
|
|
||||||
width="1em"
|
|
||||||
/>
|
|
||||||
</ButtonCircle>
|
|
||||||
</Toolbar>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -60,8 +60,6 @@ module.exports = {
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'webworkify': 'webworkify-webpack',
|
'webworkify': 'webworkify-webpack',
|
||||||
// TODO: otherwise I get a max call stack error in browser?
|
|
||||||
'mapbox-gl': path.resolve('./node_modules/mapbox-gl/dist/mapbox-gl.js')
|
|
||||||
},
|
},
|
||||||
extensions: ['', '.js', '.jsx']
|
extensions: ['', '.js', '.jsx']
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue