|
@@ -1,21 +1,135 @@
|
|
|
-import React, { Component } from 'react';
|
|
|
-import './App.css';
|
|
|
+import React, { Component } from 'react'
|
|
|
+
|
|
|
+import './App.css'
|
|
|
+import Map from 'pigeon-maps'
|
|
|
+import Marker from 'pigeon-marker'
|
|
|
+
|
|
|
+
|
|
|
import Tables from './Tables';
|
|
|
|
|
|
|
|
|
-class App extends Component {
|
|
|
- constructor(props){
|
|
|
- super(props);
|
|
|
+// please change this if you take some code from here.
|
|
|
+// otherwise the demo page will run out of credits and that would be very sad :(
|
|
|
+const MAPBOX_ACCESS_TOKEN = 'pk.eyJ1IjoicGlnZW9uLW1hcHMiLCJhIjoiY2l3eW01Y2E2MDA4dzJ6cWh5dG9pYWlwdiJ9.cvdCf-7PymM1Y3xp5j71NQ'
|
|
|
+
|
|
|
+const mapbox = (mapboxId, accessToken) => (x, y, z, dpr) => {
|
|
|
+ return `https://api.mapbox.com/styles/v1/mapbox/${mapboxId}/tiles/256/${z}/${x}/${y}${dpr >= 2 ? '@2x' : ''}?access_token=${accessToken}`
|
|
|
+}
|
|
|
+
|
|
|
+const providers = {
|
|
|
+ osm: (x, y, z) => {
|
|
|
+ const s = String.fromCharCode(97 + (x + y + z) % 3)
|
|
|
+ return `https://${s}.tile.openstreetmap.org/${z}/${x}/${y}.png`
|
|
|
+ },
|
|
|
+ wikimedia: (x, y, z, dpr) => {
|
|
|
+ return `https://maps.wikimedia.org/osm-intl/${z}/${x}/${y}${dpr >= 2 ? '@2x' : ''}.png`
|
|
|
+ },
|
|
|
+ stamen: (x, y, z, dpr) => {
|
|
|
+ return `https://stamen-tiles.a.ssl.fastly.net/terrain/${z}/${x}/${y}${dpr >= 2 ? '@2x' : ''}.jpg`
|
|
|
+ },
|
|
|
+ streets: mapbox('streets-v10', MAPBOX_ACCESS_TOKEN),
|
|
|
+ satellite: mapbox('satellite-streets-v10', MAPBOX_ACCESS_TOKEN),
|
|
|
+ outdoors: mapbox('outdoors-v10', MAPBOX_ACCESS_TOKEN),
|
|
|
+ light: mapbox('light-v9', MAPBOX_ACCESS_TOKEN),
|
|
|
+ dark: mapbox('dark-v9', MAPBOX_ACCESS_TOKEN)
|
|
|
+}
|
|
|
+
|
|
|
+const markers = {
|
|
|
+ Bernie: [[50.879, 4.6997], 13],
|
|
|
+ Martin: [[48.1542144, 13.9952128], 13],
|
|
|
+ Simon: [[50.85050, 4.35149], 11],
|
|
|
+ Lukas: [[51.0514, 3.7103], 12],
|
|
|
+}
|
|
|
+
|
|
|
+const lng2tile = (lon, zoom) => (lon + 180) / 360 * Math.pow(2, zoom)
|
|
|
+const lat2tile = (lat, zoom) => (1 - Math.log(Math.tan(lat * Math.PI / 180) + 1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, zoom)
|
|
|
+
|
|
|
+
|
|
|
+function isMapBox (provider) {
|
|
|
+ return provider === 'streets' || provider === 'satellite' || provider === 'outdoors' || provider === 'light' || provider === 'dark'
|
|
|
+}
|
|
|
+
|
|
|
+const MapboxAttribution = () => (
|
|
|
+ <span className='map-attribution'>
|
|
|
+ <span>© <a href='https://www.mapbox.com/about/maps/'>Mapbox</a></span>{' | '}
|
|
|
+ <span>© <a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a></span>{' | '}
|
|
|
+
|
|
|
+ </span>
|
|
|
+)
|
|
|
+
|
|
|
+const StamenAttribution = () => (
|
|
|
+ <span className='map-attribution'>
|
|
|
+ Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.
|
|
|
+ </span>
|
|
|
+)
|
|
|
+
|
|
|
+const WikimediaAttribution = () => (
|
|
|
+ <span className='map-attribution'>
|
|
|
+ Map tiles by <a href='https://foundation.wikimedia.org/w/index.php?title=Maps_Terms_of_Use#Where_does_the_map_data_come_from.3F'>Wikimedia</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>
|
|
|
+ </span>
|
|
|
+)
|
|
|
+
|
|
|
+export default class App extends Component {
|
|
|
+ constructor (props) {
|
|
|
+ super(props)
|
|
|
this.apiUrl = "http://alpaga.hammerle.me:9876";
|
|
|
this.name = null;
|
|
|
+
|
|
|
this.state = {
|
|
|
- persons: []
|
|
|
+ persons: [],
|
|
|
+ center: [48.1665, 14.0223], //start pos
|
|
|
+ zoom: 12,
|
|
|
+ provider: 'osm',
|
|
|
+ metaWheelZoom: false,
|
|
|
+ twoFingerDrag: false,
|
|
|
+ animate: true,
|
|
|
+ animating: false,
|
|
|
+ zoomSnap: true,
|
|
|
+ mouseEvents: true,
|
|
|
+ touchEvents: true,
|
|
|
+ minZoom: 1,
|
|
|
+ maxZoom: 18,
|
|
|
+ dragAnchor: [48.1665, 14.0223]
|
|
|
};
|
|
|
-
|
|
|
- this.componentDidMount = this.componentDidMount.bind(this)
|
|
|
+ this.componentDidMount = this.componentDidMount.bind(this)
|
|
|
}
|
|
|
|
|
|
- // is called once when loading the page
|
|
|
+ zoomIn = () => {
|
|
|
+ this.setState({
|
|
|
+ zoom: Math.min(this.state.zoom + 1, 18)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ zoomOut = () => {
|
|
|
+ this.setState({
|
|
|
+ zoom: Math.max(this.state.zoom - 1, 1)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ handleBoundsChange = ({ center, zoom, bounds, initial }) => {
|
|
|
+ if (initial) {
|
|
|
+ console.log('Got initial bounds: ', bounds)
|
|
|
+ }
|
|
|
+ this.setState({ center, zoom })
|
|
|
+ }
|
|
|
+
|
|
|
+ handleClick = ({ event, latLng, pixel }) => {
|
|
|
+ console.log('Map clicked!', latLng, pixel)
|
|
|
+ }
|
|
|
+
|
|
|
+ handleMarkerClick = ({ event, payload, anchor }) => {
|
|
|
+ console.log(`Marker #${payload} clicked at: `, anchor)
|
|
|
+ }
|
|
|
+
|
|
|
+ handleAnimationStart = () => {
|
|
|
+ this.setState({ animating: true })
|
|
|
+ }
|
|
|
+
|
|
|
+ handleAnimationStop = () => {
|
|
|
+ this.setState({ animating: false })
|
|
|
+ }
|
|
|
+
|
|
|
+// is called once when loading the page
|
|
|
componentDidMount() {
|
|
|
this.reloadLocations();
|
|
|
setInterval(this.updateLocation, 4000);
|
|
@@ -50,13 +164,69 @@ class App extends Component {
|
|
|
navigator.geolocation.getCurrentPosition(this.receivedPosition);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
|
|
|
- render (){
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ render () {
|
|
|
+ const { center, zoom, provider, animate, metaWheelZoom, twoFingerDrag, zoomSnap, mouseEvents, touchEvents, animating, minZoom, maxZoom } = this.state
|
|
|
+
|
|
|
return (
|
|
|
- <div id="wrapper">
|
|
|
- <Tables persons={this.state.persons}/>
|
|
|
|
|
|
+ <div style={{textAlign: 'center', marginTop: 50, marginLeft: 0}}>
|
|
|
+
|
|
|
+ <div style={{maxWidth: 400, margin: '0 auto'}}>
|
|
|
+ <Map
|
|
|
+ limitBounds='edge'
|
|
|
+ center={center}
|
|
|
+ zoom={zoom}
|
|
|
+ provider={providers[provider]}
|
|
|
+ dprs={[1, 2]}
|
|
|
+ onBoundsChanged={this.handleBoundsChange}
|
|
|
+ onClick={this.handleClick}
|
|
|
+ onAnimationStart={this.handleAnimationStart}
|
|
|
+ onAnimationStop={this.handleAnimationStop}
|
|
|
+ animate={animate}
|
|
|
+ metaWheelZoom={metaWheelZoom}
|
|
|
+ twoFingerDrag={twoFingerDrag}
|
|
|
+ zoomSnap={zoomSnap}
|
|
|
+ mouseEvents={mouseEvents}
|
|
|
+ touchEvents={touchEvents}
|
|
|
+ minZoom={minZoom}
|
|
|
+ maxZoom={maxZoom}
|
|
|
+ attribution={
|
|
|
+ isMapBox(provider)
|
|
|
+ ? <MapboxAttribution />
|
|
|
+ : provider === 'stamen'
|
|
|
+ ? <StamenAttribution />
|
|
|
+ : provider === 'wikimedia'
|
|
|
+ ? <WikimediaAttribution />
|
|
|
+ : null}
|
|
|
+ defaultWidth={400}
|
|
|
+ height={200}
|
|
|
+ boxClassname="pigeon-filters">
|
|
|
+
|
|
|
+ {Object.keys(markers).map(key => (
|
|
|
+ <Marker key={key} anchor={markers[key][0]} payload={key} onClick={this.handleMarkerClick} />
|
|
|
+ ))}
|
|
|
+
|
|
|
+ {isMapBox(provider) && <span className='mapbox-wordmark' />}
|
|
|
+ </Map>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+
|
|
|
+ {' '}
|
|
|
+ {Math.round(center[0] * 10000) / 10000} ({lat2tile(center[0], zoom)})
|
|
|
+ {' x '}
|
|
|
+ {Math.round(center[1] * 10000) / 10000} ({lng2tile(center[1], zoom)})
|
|
|
+ {' @ '}
|
|
|
+ {Math.round(zoom * 100) / 100}
|
|
|
+ {' - '}
|
|
|
+ {animating ? 'animating' : 'stopped'}
|
|
|
+
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div>
|
|
|
<button
|
|
|
onClick={ () => {
|
|
|
this.name = "Bernie";
|
|
@@ -74,10 +244,13 @@ class App extends Component {
|
|
|
this.name = "Lukas";
|
|
|
}}> Lukas </button>
|
|
|
</div>
|
|
|
- );
|
|
|
+
|
|
|
+
|
|
|
+ <div id="wrapper">
|
|
|
+ <Tables persons={this.state.persons}/>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ )
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-export default App;
|