diff options
Diffstat (limited to 'src/client/views/nodes/MapBox/MapBox.tsx')
-rw-r--r-- | src/client/views/nodes/MapBox/MapBox.tsx | 153 |
1 files changed, 55 insertions, 98 deletions
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index c25d10a0d..efe0a3620 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -1,72 +1,45 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import BingMapsReact from 'bingmaps-react'; -// import 'mapbox-gl/dist/mapbox-gl.css'; - -import { Button, EditableText, IconButton, Size, Type } from 'browndash-components'; -import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, flow, toJS, autorun, makeObservable } from 'mobx'; +import { IconButton, Size, Type } from 'browndash-components'; +import { IReactionDisposer, ObservableMap, action, autorun, computed, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { Utils, emptyFunction, setupMoveUpEvents } from '../../../../Utils'; import { Doc, DocListCast, Field, LinkedTo, Opt } from '../../../../fields/Doc'; import { DocCss, Highlight } from '../../../../fields/DocSymbols'; -import { Id } from '../../../../fields/FieldSymbols'; -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 { DocCast, NumCast, StrCast } from '../../../../fields/Types'; import { DocumentType } from '../../../documents/DocumentTypes'; +import { DocUtils, Docs } from '../../../documents/Documents'; import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager } from '../../../util/DragManager'; import { LinkManager } from '../../../util/LinkManager'; import { SnappingManager } from '../../../util/SnappingManager'; -import { Transform } from '../../../util/Transform'; -import { undoable, UndoManager } from '../../../util/UndoManager'; -import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm'; +import { UndoManager, undoable } from '../../../util/UndoManager'; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocComponent'; -import { Colors } from '../../global/globalEnums'; import { SidebarAnnos } from '../../SidebarAnnos'; +import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm'; +import { Colors } from '../../global/globalEnums'; import { DocumentView } from '../DocumentView'; import { FieldView, FieldViewProps } from '../FieldView'; import { FormattedTextBox } from '../formattedText/FormattedTextBox'; import { PinProps, PresBox } from '../trails'; import { MapAnchorMenu } from './MapAnchorMenu'; -import { - Map as MapboxMap, - MapRef, - Marker, - ControlPosition, - FullscreenControl, - MapProvider, - MarkerProps, - NavigationControl, - ScaleControl, - ViewState, - ViewStateChangeEvent, - useControl, - GeolocateControl, - Popup, - MapEvent, - Source, - Layer, -} from 'react-map-gl'; +import { ControlPosition, Layer, MapProvider, MapRef, Map as MapboxMap, Marker, MarkerProps, Source, ViewState, ViewStateChangeEvent } from 'react-map-gl'; import MapboxGeocoder, { GeocoderOptions } from '@mapbox/mapbox-gl-geocoder!'; import './MapBox.scss'; -import { NumberLiteralType } from 'typescript'; // import { GeocoderControl } from './GeocoderControl'; -import mapboxgl, { LngLat, LngLatBoundsLike, LngLatLike, MapLayerMouseEvent, MercatorCoordinate } from 'mapbox-gl!'; -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, Checkbox, FormControlLabel, TextField } from '@mui/material'; -import { List } from '../../../../fields/List'; -import { listSpec } from '../../../../fields/Schema'; -import { IconLookup, faCircleXmark, faFileExport, faGear, faMinus, faPause, faPlay, faPlus, faRotate } from '@fortawesome/free-solid-svg-icons'; -import { MarkerIcons } from './MarkerIcons'; -import { SettingsManager } from '../../../util/SettingsManager'; +import { IconLookup, faCircleXmark, faGear, faPause, faPlay, faRotate } from '@fortawesome/free-solid-svg-icons'; +import { Checkbox, FormControlLabel, TextField } from '@mui/material'; import * as turf from '@turf/turf'; import * as d3 from 'd3'; -import { AnimationSpeed, AnimationStatus, AnimationUtility } from './AnimationUtility'; -import { fastSpeedIcon, mediumSpeedIcon, slowSpeedIcon } from './AnimationSpeedIcons'; +import { Feature, FeatureCollection, GeoJsonProperties, Geometry, LineString, Position } from 'geojson'; +import mapboxgl, { LngLat, LngLatBoundsLike, MapLayerMouseEvent } from 'mapbox-gl!'; import { CirclePicker, ColorResult } from 'react-color'; +import { MarkerEvent } from 'react-map-gl/dist/esm/types'; +import { fastSpeedIcon, mediumSpeedIcon, slowSpeedIcon } from './AnimationSpeedIcons'; +import { AnimationSpeed, AnimationStatus, AnimationUtility } from './AnimationUtility'; +import { MapboxApiUtility, TransportationType } from './MapboxApiUtility'; +import { MarkerIcons } from './MarkerIcons'; // amongus /** @@ -891,15 +864,16 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps }, 'createpin'); @action - createMapRoute = undoable((coordinates: Position[], origin: string, destination: any, createPinForDestination: boolean) => { - const mapRoute = Docs.Create.MapRouteDocument(false, [], { title: `${origin} --> ${destination.place_name}`, routeCoordinates: JSON.stringify(coordinates) }); - this.addDocument(mapRoute, this.annotationKey); - if (createPinForDestination) { - this.createPushpin(destination.center[1], destination.center[0], destination.place_name); + createMapRoute = undoable((coordinates: Position[], originName: string, destination: any, createPinForDestination: boolean) => { + if (originName !== destination.place_name) { + const mapRoute = Docs.Create.MapRouteDocument(false, [], { title: `${originName} --> ${destination.place_name}`, routeCoordinates: JSON.stringify(coordinates) }); + this.addDocument(mapRoute, this.annotationKey); + if (createPinForDestination) { + this.createPushpin(destination.center[1], destination.center[0], destination.place_name); + } + return mapRoute; } - return mapRoute; - - // mapMarker.infoWindowOpen = true; + // TODO: Display error that can't create route to same location }, 'createmaproute'); searchbarKeyDown = (e: any) => e.key === 'Enter' && this.bingSearch(); @@ -958,6 +932,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps @action handleMapClick = (e: MapLayerMouseEvent) => { + this.featuresFromGeocodeResults = []; if (this._mapRef.current) { const features = this._mapRef.current.queryRenderedFeatures(e.point, { layers: ['map-routes-layer'], @@ -1146,24 +1121,26 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps if (routeDoc) { MapAnchorMenu.Instance.fadeOut(true); document.removeEventListener('pointerdown', this.tryHideMapAnchorMenu, true); + this.featuresFromGeocodeResults = []; this.routeToAnimate = routeDoc; } }; - @observable - mapboxMapViewState: ViewState = { - zoom: this.dataDoc.map_zoom ? NumCast(this.dataDoc.map_zoom) : 8, - longitude: this.dataDoc.longitude ? NumCast(this.dataDoc.longitude) : -71.4128, - latitude: this.dataDoc.latitude ? NumCast(this.dataDoc.latitude) : 41.824, - pitch: this.dataDoc.map_pitch ? NumCast(this.dataDoc.map_pitch) : 0, - bearing: this.dataDoc.map_bearing ? NumCast(this.dataDoc.map_bearing) : 0, - padding: { - top: 0, - bottom: 0, - left: 0, - right: 0, - }, - }; + @computed get mapboxMapViewState(): ViewState { + return { + zoom: NumCast(this.dataDoc.map_zoom, 8), + longitude: NumCast(this.dataDoc.longitude, -71.4128), + latitude: NumCast(this.dataDoc.latitude, 41.824), + pitch: NumCast(this.dataDoc.map_pitch), + bearing: NumCast(this.dataDoc.map_bearing), + padding: { + top: 0, + bottom: 0, + left: 0, + right: 0, + }, + }; + } @computed get preAnimationViewState() { @@ -1390,9 +1367,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps this.routeToAnimate = undefined; this.animationUtility = null; } - if (this.preAnimationViewState) { - this.mapboxMapViewState = this.preAnimationViewState; - } }; @action @@ -1488,10 +1462,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps const fixedBearing = Math.max(0, Math.min(360, bearing)); this._mapRef.current.setBearing(fixedBearing); this.dataDoc.map_bearing = fixedBearing; - this.mapboxMapViewState = { - ...this.mapboxMapViewState, - bearing: fixedBearing, - }; } }; @@ -1502,10 +1472,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps const fixedPitch = Math.max(0, Math.min(85, pitch)); this._mapRef.current.setPitch(fixedPitch); this.dataDoc.map_pitch = fixedPitch; - this.mapboxMapViewState = { - ...this.mapboxMapViewState, - pitch: fixedPitch, - }; } }; @@ -1516,10 +1482,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps const fixedZoom = Math.max(0, Math.min(16, zoom)); this._mapRef.current.setZoom(fixedZoom); this.dataDoc.map_zoom = fixedZoom; - this.mapboxMapViewState = { - ...this.mapboxMapViewState, - zoom: fixedZoom, - }; } }; @@ -1529,23 +1491,18 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps let newZoom: number; if (increment) { console.log('inc'); - newZoom = this.mapboxMapViewState.zoom + 1; + newZoom = Math.min(16, this.mapboxMapViewState.zoom + 1); } else { console.log('dec'); - newZoom = this.mapboxMapViewState.zoom - 1; + newZoom = Math.max(0, this.mapboxMapViewState.zoom - 1); } this._mapRef.current.setZoom(newZoom); this.dataDoc.map_zoom = newZoom; - this.mapboxMapViewState = { - ...this.mapboxMapViewState, - zoom: increment ? Math.min(16, newZoom) : Math.max(0, newZoom), - }; } }; @action onMapMove = (e: ViewStateChangeEvent) => { - this.mapboxMapViewState = e.viewState; this.dataDoc.longitude = e.viewState.longitude; this.dataDoc.latitude = e.viewState.latitude; }; @@ -1581,8 +1538,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps }), MapBox._rerenderDelay); return null; } - const scale = this._props.NativeDimScaling?.() || 1; + const parscale = scale === 1 ? 1 : this._props.ScreenToLocalTransform().Scale ?? 1; const renderAnnotations = (childFilters?: () => string[]) => null; return ( @@ -1593,7 +1550,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps onPointerDown={async e => { e.button === 0 && !e.ctrlKey && e.stopPropagation(); }} - style={{ width: `calc(100% - ${this.sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}> + style={{ transformOrigin: 'top left', transform: `scale(${scale})`, width: `calc(100% - ${this.sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}> <div style={{ mixBlendMode: 'multiply' }}>{renderAnnotations(this.transparentFilter)}</div> {renderAnnotations(this.opaqueFilter)} {SnappingManager.IsDragging ? null : renderAnnotations()} @@ -1639,7 +1596,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps </div> )} {this.routeToAnimate && ( - <div className="animation-panel"> + <div className="animation-panel" style={{ width: this.sidebarWidth() === 0 ? '100%' : `calc(100% - ${this.sidebarWidth()}px)` }}> <div id="route-to-animate-title">{StrCast(this.routeToAnimate.title)}</div> <div className="route-animation-options">{this.getRouteAnimationOptions()}</div> </div> @@ -1683,15 +1640,15 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps <MapboxMap ref={this._mapRef} mapboxAccessToken={MAPBOX_ACCESS_TOKEN} - id="mapbox-map" - viewState={{ ...this.mapboxMapViewState, width: NumCast(this.layoutDoc._width) / scale, height: NumCast(this.layoutDoc._height) / scale }} + viewState={this.isAnimating ? undefined : { ...this.mapboxMapViewState, width: NumCast(this.layoutDoc._width), height: NumCast(this.layoutDoc._height) }} mapStyle={this.dataDoc.map_style ? StrCast(this.dataDoc.map_style) : 'mapbox://styles/mapbox/streets-v11'} style={{ - transformOrigin: 'center', - transform: `scale(${scale < 1 ? 1 : scale})`, + position: 'absolute', + top: 0, + left: 0, zIndex: '0', - width: '100%', - height: '100%', + width: NumCast(this.layoutDoc._width) * parscale, + height: NumCast(this.layoutDoc._height) * parscale, }} initialViewState={this.isAnimating ? undefined : this.mapboxMapViewState} onMove={this.onMapMove} |