aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/MapBox/MapBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/MapBox/MapBox.tsx')
-rw-r--r--src/client/views/nodes/MapBox/MapBox.tsx288
1 files changed, 214 insertions, 74 deletions
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index 2b563faf2..ac926e1fb 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -9,7 +9,7 @@ import * as React from 'react';
import { Doc, DocListCast, Field, LinkedTo, Opt } from '../../../../fields/Doc';
import { DocCss, Highlight } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
-import { DocCast, NumCast, StrCast } from '../../../../fields/Types';
+import { Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, setupMoveUpEvents, Utils } from '../../../../Utils';
import { Docs, DocUtils } from '../../../documents/Documents';
import { DocumentType } from '../../../documents/DocumentTypes';
@@ -52,11 +52,13 @@ import './MapBox.scss';
import { NumberLiteralType } from 'typescript';
// import { GeocoderControl } from './GeocoderControl';
import mapboxgl, { LngLat, MapLayerMouseEvent } from 'mapbox-gl';
-import { Feature, FeatureCollection } from 'geojson';
+import { Feature, FeatureCollection, GeoJsonProperties, Geometry, LineString, MultiLineString, Position } from 'geojson';
import { MarkerEvent } from 'react-map-gl/dist/esm/types';
import { MapboxApiUtility, TransportationType} from './MapboxApiUtility';
-import { Autocomplete, TextField } from '@mui/material';
+import { Autocomplete, Checkbox, FormControlLabel, TextField } from '@mui/material';
import { List } from '../../../../fields/List';
+import { listSpec } from '../../../../fields/Schema';
+import { IconLookup, faGear } from '@fortawesome/free-solid-svg-icons';
// amongus
/**
@@ -140,15 +142,17 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
@computed get allRoutes() {
return this.allAnnotations.filter(anno => anno.type === DocumentType.MAPROUTE);
}
- @computed get allRoutesGeoJson() {
- const features = this.allRoutes.map(route => {
+ @computed get allRoutesGeoJson(): FeatureCollection {
+ const features: Feature<Geometry, GeoJsonProperties>[] = this.allRoutes.map(route => {
+ console.log("Route coords: ", route.coordinates);
+ const geometry: LineString = {
+ type: 'LineString',
+ coordinates: JSON.parse(StrCast(route.coordinates))
+ }
return {
type: 'Feature',
properties: {},
- geometry: {
- type: 'LineString',
- coordinates: route.coordinates
- }
+ geometry: geometry
};
});
@@ -771,7 +775,14 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
NumCast(longitude),
false,
[],
- {title: location ?? `lat=${latitude},lng=${longitude}`, map: location, description: "", wikiData: wikiData},
+ {
+ title: location ?? `lat=${latitude},lng=${longitude}`,
+ map: location,
+ description: "",
+ wikiData: wikiData,
+ markerType: 'MAPBOX_MARKER',
+ markerColor: '#3FB1CE'
+ },
// { title: map ?? `lat=${latitude},lng=${longitude}`, map: map },
// ,'pushpinIDamongus'+ this.incrementer++
);
@@ -783,11 +794,12 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}, 'createpin');
@action
- createMapRoute = undoable((coordinates: List<any>, origin: string, destination: string) => {
+ createMapRoute = undoable((coordinates: Position[], origin: string, destination: string) => {
+ console.log(coordinates);
const mapRoute = Docs.Create.MapRouteDocument(
false,
[],
- {title: `${origin} -> ${destination}`, routeCoordinates: coordinates},
+ {title: `${origin} -> ${destination}`, routeCoordinates: JSON.stringify(coordinates)},
);
this.addDocument(mapRoute, this.annotationKey);
return mapRoute;
@@ -800,29 +812,11 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
- @observable
- mapboxMapViewState: ViewState = {
- zoom: 9,
- longitude: -71.41,
- latitude: 41.82,
- pitch: 0,
- bearing: 0,
- padding: {
- top: 0,
- bottom: 0,
- left: 0,
- right: 0
- }
- }
+
@observable
featuresFromGeocodeResults: any[] = [];
- @action
- onMapMove = (e: ViewStateChangeEvent) => {
- this.mapboxMapViewState = e.viewState;
- }
-
@action
addMarkerForFeature = (feature: any) => {
@@ -838,6 +832,12 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
location,
wikiData
)
+
+ if (this._mapRef.current){
+ this._mapRef.current.flyTo({
+ center: feature.center
+ });
+ }
this.featuresFromGeocodeResults = [];
} else {
@@ -855,6 +855,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
const features = await MapboxApiUtility.forwardGeocodeForFeatures(searchText);
if (features){
runInAction(() => {
+ this.settingsOpen= false;
this.featuresFromGeocodeResults = features;
})
}
@@ -988,6 +989,75 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
+ @observable
+ mapboxMapViewState: ViewState = {
+ zoom: 9,
+ longitude: -71.45,
+ latitude: 41.82,
+ pitch: 0,
+ bearing: 0,
+ padding: {
+ top: 0,
+ bottom: 0,
+ left: 0,
+ right: 0
+ }
+ }
+
+ @observable
+ settingsOpen: boolean = false;
+
+ @observable
+ mapStyle: string = 'mapbox://styles/mapbox/streets-v12'
+
+ @observable
+ showTerrain: boolean = false;
+
+ @action
+ toggleSettings = () => {
+ this.featuresFromGeocodeResults = [];
+ this.settingsOpen = !this.settingsOpen;
+ }
+
+ @action
+ changeMapStyle = (e: React.ChangeEvent<HTMLSelectElement>) => {
+ this.mapStyle = `mapbox://styles/mapbox/${e.target.value}`
+ }
+
+ @action
+ onMapMove = (e: ViewStateChangeEvent) => {
+ this.mapboxMapViewState = e.viewState;
+ }
+
+ @action
+ toggleShowTerrain = () => {
+ this.showTerrain = !this.showTerrain;
+ }
+
+ @action
+ onBearingChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+ const newVal = parseInt(e.target.value)
+ if (!isNaN(newVal) && newVal >= 0){
+ this.mapboxMapViewState = {
+ ...this.mapboxMapViewState,
+ bearing: parseInt(e.target.value)
+ }
+ }
+ }
+
+ @action
+ onPitchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+ const newVal = parseInt(e.target.value);
+ if (!isNaN(newVal) && newVal >= 0){
+ this.mapboxMapViewState = {
+ ...this.mapboxMapViewState,
+ pitch: parseInt(e.target.value)
+ }
+ }
+ }
+
+
+
static _firstRender = true;
static _rerenderDelay = 500;
@@ -1029,51 +1099,59 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
placeholder='Enter a location'
onChange={(e) => this.handleSearchChange(e.target.value)}
/>
- {/* <Autocomplete
- fullWidth
- id="map-location-searcher"
- freeSolo
- onInputChange={(e, searchText) => this.handleSearchChange(searchText)}
- onChange={(e, selectedOption) => {
- this.handleSearchChange(""); // clear input
- this.addMarkerForFeature(selectedOption);
- }}
- options={this.featuresFromGeocodeResults
- .filter(feature => feature.place_name)
- .map(feature => feature)}
- getOptionLabel={(feature) => feature.place_name}
- renderInput={(params) => (
- <TextField
- {...params}
- placeholder='Enter a location'
- />
- )}
- /> */}
- {/* <EditableText
- // editing
- setVal={(newText: string | number) => typeof newText === 'string' && this.handleSearchChange(newText)}
- // onEnter={e => this.bingSearch()}
- onEnter={e => {}}
- height={32}
- // placeholder={this.bingSearchBarContents || 'Enter a location'}
- placeholder='Enter a location'
- textAlign="center"
- /> */}
- {/* <IconButton
- icon={
- <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="magnifying-glass" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" color="#DFDFDF">
- <path
- fill="currentColor"
- d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z"></path>
- </svg>
- }
- onClick={this.bingSearch}
+ <IconButton
+ icon={<FontAwesomeIcon icon={faGear as IconLookup} size='1x'/>}
type={Type.TERT}
+ onClick={(e) => this.toggleSettings()}
+
/>
- <div style={{ width: 30, height: 30 }} ref={this._dragRef} onPointerDown={this.dragToggle}>
- <Button tooltip="drag to place a pushpin" icon={<FontAwesomeIcon size={'lg'} icon={'bullseye'} />} />
- </div> */}
</div>
+ {this.settingsOpen &&
+ <div className='mapbox-settings-panel' style={{right: `${0+ this.sidebarWidth()}px`}}>
+ <div className='mapbox-style-select'>
+ <div>
+ Map Style:
+ </div>
+ <div>
+ <select onChange={this.changeMapStyle}>
+ <option value='streets-v12'>Streets</option>
+ <option value='outdoors-v12'>Outdoors</option>
+ <option value='light-v11'>Light</option>
+ <option value='dark-v11'>Dark</option>
+ <option value='satellite-v9'>Satellite</option>
+ <option value='satellite-streets-v12'>Satellite Streets</option>
+ <option value='navigation-day-v1'>Navigation Day</option>
+ <option value='navigation-night-v1'>Navigation Night</option>
+ </select>
+ </div>
+ </div>
+ <div className='mapbox-bearing-selection'>
+ <div>Bearing: </div>
+ <input
+ value={this.mapboxMapViewState.bearing}
+ min={0}
+ type='number'
+ onChange={this.onBearingChange}/>
+ </div>
+ <div className='mapbox-pitch-selection'>
+ <div>Pitch: </div>
+ <input
+ value={this.mapboxMapViewState.pitch}
+ min={0}
+ type='number'
+ onChange={this.onPitchChange}/>
+ </div>
+ <div className='mapbox-terrain-selection'>
+ <div>Show terrain: </div>
+ <input
+ type='checkbox'
+ checked={this.showTerrain}
+ onChange={this.toggleShowTerrain}
+ />
+ </div>
+ </div>
+ }
+
<div className='mapbox-geocoding-search-results'>
{this.featuresFromGeocodeResults.length > 0 && (
<React.Fragment>
@@ -1107,15 +1185,24 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}}
mapboxAccessToken={MAPBOX_ACCESS_TOKEN}
id="mapbox-map"
- mapStyle="mapbox://styles/mapbox/streets-v9"
+ mapStyle={this.mapStyle}
style={{height: '100%', width: '100%'}}
{...this.mapboxMapViewState}
onMove={this.onMapMove}
onDblClick={this.handleMapClick}
+ terrain={this.showTerrain ? { source: 'mapbox-dem', exaggeration: 2.0 } : undefined}
>
+ <Source
+ id="mapbox-dem"
+ type="raster-dem"
+ url="mapbox://mapbox.mapbox-terrain-dem-v1"
+ tileSize={512}
+ maxzoom={14}
+ />
<Source id='temporary-route' type='geojson' data={this.temporaryRouteSource}/>
+ <Source id='map-routes' type='geojson' data={this.allRoutesGeoJson}/>
<Layer
id='temporary-route-layer'
type='line'
@@ -1123,6 +1210,14 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
layout={{"line-join": "round", "line-cap": "round"}}
paint={{"line-color": "#36454F", "line-width": 4, "line-dasharray": [1,1]}}
/>
+ <Layer
+ id='map-routes-layer'
+ type='line'
+ source='map-routes'
+ layout={{"line-join": "round", "line-cap": "round"}}
+ paint={{"line-color": "#FF0000", "line-width": 4}}
+ />
+
<>
{this.allPushpins
// .filter(anno => !anno.layout_unrendered)
@@ -1219,3 +1314,48 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
);
}
}
+
+{/* <Autocomplete
+ fullWidth
+ id="map-location-searcher"
+ freeSolo
+ onInputChange={(e, searchText) => this.handleSearchChange(searchText)}
+ onChange={(e, selectedOption) => {
+ this.handleSearchChange(""); // clear input
+ this.addMarkerForFeature(selectedOption);
+ }}
+ options={this.featuresFromGeocodeResults
+ .filter(feature => feature.place_name)
+ .map(feature => feature)}
+ getOptionLabel={(feature) => feature.place_name}
+ renderInput={(params) => (
+ <TextField
+ {...params}
+ placeholder='Enter a location'
+ />
+ )}
+ /> */}
+ {/* <EditableText
+ // editing
+ setVal={(newText: string | number) => typeof newText === 'string' && this.handleSearchChange(newText)}
+ // onEnter={e => this.bingSearch()}
+ onEnter={e => {}}
+ height={32}
+ // placeholder={this.bingSearchBarContents || 'Enter a location'}
+ placeholder='Enter a location'
+ textAlign="center"
+ /> */}
+ {/* <IconButton
+ icon={
+ <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="magnifying-glass" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" color="#DFDFDF">
+ <path
+ fill="currentColor"
+ d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z"></path>
+ </svg>
+ }
+ onClick={this.bingSearch}
+ type={Type.TERT}
+ />
+ <div style={{ width: 30, height: 30 }} ref={this._dragRef} onPointerDown={this.dragToggle}>
+ <Button tooltip="drag to place a pushpin" icon={<FontAwesomeIcon size={'lg'} icon={'bullseye'} />} />
+ </div> */} \ No newline at end of file