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",
|
||||
"dependencies": {
|
||||
"mapbox-gl": "^0.23.0",
|
||||
"mapbox-gl-style-spec": "^8.8.0",
|
||||
"node-sass": "^3.9.2",
|
||||
"react": "15.3.0",
|
||||
"react-dom": "15.3.0",
|
||||
"react-file-reader-input": "^1.1.0",
|
||||
"react-geomicons": "^2.0.5",
|
||||
"react-icons": "^2.2.1",
|
||||
"react-mapbox-gl": "^0.11.0",
|
||||
"react-tap-event-plugin": "^1.0.0",
|
||||
"rebass": "^0.3.1",
|
||||
"sass-loader": "^4.0.1"
|
||||
|
|
48
src/app.jsx
48
src/app.jsx
|
@ -1,14 +1,21 @@
|
|||
import {Workspace} from './workspace.jsx';
|
||||
import {Map} from './map.jsx';
|
||||
import {Toolbar} from './toolbar.jsx';
|
||||
import React from 'react';
|
||||
import styles from './layout.scss';
|
||||
import React from 'react'
|
||||
|
||||
import { Drawer, Container, Block, Fixed } from 'rebass'
|
||||
import {Map} from './map.jsx'
|
||||
import {Toolbar} from './toolbar.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 {
|
||||
render() {
|
||||
let editor = null
|
||||
|
||||
if(this.props.mapStyle) {
|
||||
editor = <LayerEditor layers={this.props.mapStyle.layers}/>
|
||||
}
|
||||
|
||||
return <Container style={{
|
||||
zIndex: 100,
|
||||
position: "fixed",
|
||||
|
@ -19,8 +26,8 @@ export class WorkspaceDrawer extends React.Component {
|
|||
bottom: "0",
|
||||
backgroundColor: theme.colors.gray}
|
||||
} >
|
||||
<LayerEditor />
|
||||
</Container>;
|
||||
{editor}
|
||||
</Container>
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,6 +37,18 @@ export default class App extends React.Component {
|
|||
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 () {
|
||||
return {
|
||||
rebass: theme,
|
||||
|
@ -40,14 +59,13 @@ export default class App extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Toolbar />
|
||||
<WorkspaceDrawer />
|
||||
<div className={styles.layoutMap}>
|
||||
<Map />
|
||||
console.log(this.state.mapStyle)
|
||||
return <div>
|
||||
<Toolbar onStyleUpload={this.updateStyle} />
|
||||
<WorkspaceDrawer mapStyle={this.state.mapStyle} />
|
||||
<div className={layout.map}>
|
||||
<Map mapStyle={this.state.mapStyle} />
|
||||
</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 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 {
|
||||
render() {
|
||||
const layerBlocks = this.props.layers.map(layer => {
|
||||
console.log(layer)
|
||||
return <Text>{layer.id}</Text>
|
||||
});
|
||||
return <Container>
|
||||
<Toolbar>
|
||||
<NavItem is="a">
|
||||
Toolbar
|
||||
</NavItem>
|
||||
</Toolbar>
|
||||
</Container>;
|
||||
{layerBlocks}
|
||||
</Container>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
.layoutMap {
|
||||
.map {
|
||||
@include full-height;
|
||||
width: 100%;
|
||||
|
||||
|
|
21
src/map.jsx
21
src/map.jsx
|
@ -1,21 +1,18 @@
|
|||
import React from 'react';
|
||||
import MapboxGl from 'mapbox-gl';
|
||||
import React from 'react'
|
||||
import ReactMapboxGl from "react-mapbox-gl"
|
||||
|
||||
export class Map extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
MapboxGl.accessToken = "pk.eyJ1IjoibW9yZ2Vua2FmZmVlIiwiYSI6IjIzcmN0NlkifQ.0LRTNgCc-envt9d5MzR75w";
|
||||
const map = new MapboxGl.Map({
|
||||
container: this.container,
|
||||
style: "mapbox://styles/morgenkaffee/cirqasdb8003dh1ntbo6dkvs6"
|
||||
});
|
||||
super(props)
|
||||
}
|
||||
|
||||
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';
|
||||
|
||||
export class StyleCommand {
|
||||
do(map) {
|
||||
throw new TypeError("Do not implemented");
|
||||
}
|
||||
undo(map) {
|
||||
throw new TypeError("Undo not implemented");
|
||||
}
|
||||
// A wrapper around Mapbox GL style
|
||||
export class Style {
|
||||
constructor() {
|
||||
this.styleHistory = [];
|
||||
this.renderers = [];
|
||||
}
|
||||
|
||||
export class StyleEditor {
|
||||
constructor(map, style) {
|
||||
this.map = map;
|
||||
this.style = style;
|
||||
this.history = [];
|
||||
load(style) {
|
||||
this.currentStyle = style;
|
||||
}
|
||||
|
||||
onRender(cb) {
|
||||
this.renderers.push(cb);
|
||||
}
|
||||
|
||||
update(style) {
|
||||
this.styleHistory.push(this.currentStyle);
|
||||
this.currentStyle = style;
|
||||
this.renderers.forEach(r => r(this.currentStyle))
|
||||
}
|
||||
|
||||
layers() {
|
||||
return this.style.layers;
|
||||
}
|
||||
|
||||
execute(command) {
|
||||
this.history.push(command);
|
||||
command.do(this.map);
|
||||
return this.currentStyle.layers;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
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 { 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 {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
styleFile: null
|
||||
};
|
||||
this.onUpload = this.onUpload.bind(this);
|
||||
}
|
||||
|
||||
onUpload(_, files) {
|
||||
|
@ -20,10 +19,11 @@ export class Toolbar extends React.Component {
|
|||
reader.readAsText(file, "UTF-8");
|
||||
reader.onload = e => {
|
||||
const style = JSON.parse(e.target.result);
|
||||
console.log(style);
|
||||
this.props.onStyleUpload(style);
|
||||
}
|
||||
reader.onerror = e => console.log(e.target);
|
||||
}
|
||||
|
||||
render() {
|
||||
return <Container style={{
|
||||
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: {
|
||||
alias: {
|
||||
'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']
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue