From 3a22a2a2c78bd7d5af2b68541564a429be2864b9 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 15 Dec 2023 13:34:18 -0500 Subject: map box merging --- src/client/views/nodes/MapBox/AnimationUtility.ts | 16 +- src/client/views/nodes/MapBox/MapBox.tsx | 962 +++++++++------------- 2 files changed, 421 insertions(+), 557 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/MapBox/AnimationUtility.ts b/src/client/views/nodes/MapBox/AnimationUtility.ts index a5cff4668..42dfa59b7 100644 --- a/src/client/views/nodes/MapBox/AnimationUtility.ts +++ b/src/client/views/nodes/MapBox/AnimationUtility.ts @@ -7,7 +7,7 @@ import * as turf from '@turf/turf'; import { Position } from '@turf/turf'; import { Feature, FeatureCollection, GeoJsonProperties, Geometry } from 'geojson'; import { observer } from 'mobx-react'; -import { action, computed, observable, runInAction } from 'mobx'; +import { action, computed, observable, runInAction, makeObservable } from 'mobx'; export enum AnimationStatus { START = 'start', @@ -26,16 +26,16 @@ export class AnimationUtility { private ROUTE_COORDINATES: Position[] = []; @observable - private PATH: turf.helpers.Feature; + private PATH?: turf.helpers.Feature = undefined; - private PATH_DISTANCE: number; + private PATH_DISTANCE: number = 0; private FLY_IN_START_PITCH = 40; - private FIRST_LNG_LAT: { lng: number; lat: number }; + private FIRST_LNG_LAT: { lng: number; lat: number } = { lng: 0, lat: 0 }; private START_ALTITUDE = 3_000_000; - private MAP_REF: MapRef | null; + private MAP_REF: MapRef | null = null; - @observable private isStreetViewAnimation: boolean; - @observable private animationSpeed: AnimationSpeed; + @observable private isStreetViewAnimation: boolean = false; + @observable private animationSpeed: AnimationSpeed = AnimationSpeed.MEDIUM; @observable private previousLngLat: { lng: number; lat: number }; @@ -174,6 +174,7 @@ export class AnimationUtility { }; constructor(firstLngLat: { lng: number; lat: number }, routeCoordinates: Position[], isStreetViewAnimation: boolean, animationSpeed: AnimationSpeed, terrainDisplayed: boolean, mapRef: MapRef | null) { + makeObservable(this); this.FIRST_LNG_LAT = firstLngLat; this.previousLngLat = firstLngLat; this.isStreetViewAnimation = isStreetViewAnimation; @@ -232,6 +233,7 @@ export class AnimationUtility { return; } + if (!this.PATH) return; // calculate the distance along the path based on the animationPhase const alongPath = turf.along(this.PATH, this.PATH_DISTANCE * animationPhase).geometry.coordinates; diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 724c1a770..735c04c1d 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -3,7 +3,7 @@ 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} from 'mobx'; +import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, flow, toJS, autorun, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast, Field, LinkedTo, Opt } from '../../../../fields/Doc'; @@ -28,36 +28,34 @@ import { FieldView, FieldViewProps } from '../FieldView'; import { FormattedTextBox } from '../formattedText/FormattedTextBox'; import { PinProps, PresBox } from '../trails'; import { MapAnchorMenu } from './MapAnchorMenu'; -import * as HME from "h264-mp4-encoder"; -import {simd} from 'wasm-feature-detect'; -import { +import { Map as MapboxMap, MapRef, - Marker, - ControlPosition, - FullscreenControl, - MapProvider, - MarkerProps, - NavigationControl, - ScaleControl, - ViewState, + Marker, + ControlPosition, + FullscreenControl, + MapProvider, + MarkerProps, + NavigationControl, + ScaleControl, + ViewState, ViewStateChangeEvent, useControl, GeolocateControl, Popup, MapEvent, Source, - Layer} from 'react-map-gl'; -import MapboxGeocoder, {GeocoderOptions} from '@mapbox/mapbox-gl-geocoder'; -import debounce from 'debounce'; + Layer, +} 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 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 { MapboxApiUtility, TransportationType } from './MapboxApiUtility'; import { Autocomplete, Checkbox, FormControlLabel, TextField } from '@mui/material'; import { List } from '../../../../fields/List'; import { listSpec } from '../../../../fields/Schema'; @@ -65,10 +63,10 @@ import { IconLookup, faCircleXmark, faFileExport, faGear, faMinus, faPause, faPl import { MarkerIcons } from './MarkerIcons'; import { SettingsManager } from '../../../util/SettingsManager'; import * as turf from '@turf/turf'; -import * as d3 from "d3"; +import * as d3 from 'd3'; import { AnimationSpeed, AnimationStatus, AnimationUtility } from './AnimationUtility'; import { fastSpeedIcon, mediumSpeedIcon, slowSpeedIcon } from './AnimationSpeedIcons'; -import { CirclePicker, ColorState } from 'react-color'; +import { CirclePicker, ColorResult } from 'react-color'; // amongus /** @@ -91,24 +89,24 @@ const MAPBOX_FORWARD_GEOCODE_BASE_URL = 'https://api.mapbox.com/geocoding/v5/map const MAPBOX_REVERSE_GEOCODE_BASE_URL = 'https://api.mapbox.com/geocoding/v5/mapbox.places/'; type PopupInfo = { - longitude: number, - latitude: number, - title: string, - description: string -} + longitude: number; + latitude: number; + title: string; + description: string; +}; export type GeocoderControlProps = Omit & { - mapboxAccessToken: string, + mapboxAccessToken: string; marker?: Omit; position: ControlPosition; onResult: (...args: any[]) => void; -} +}; type MapMarker = { - longitude: number, - latitude: number -} + longitude: number; + latitude: number; +}; /** * Consider integrating later: allows for drawing, circling, making shapes on map @@ -138,6 +136,11 @@ export class MapBox extends ViewBoxAnnotatableComponent) => void); + constructor(props: any) { + super(props); + makeObservable(this); + } + @observable private _savedAnnotations = new ObservableMap(); @computed get allSidebarDocs() { return DocListCast(this.dataDoc[this.SidebarKey]); @@ -157,7 +160,7 @@ export class MapBox extends ViewBoxAnnotatableComponent; @@ -173,7 +176,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { const animationUtil = this.animationUtility; const concattedCoordinates = geometry.coordinates.concat(originalCoordinates.slice(endIndex)); @@ -210,28 +213,28 @@ export class MapBox extends ViewBoxAnnotatableComponent runInAction(() => { - const localDelta = this.props + const localDelta = this._props .ScreenToLocalTransform() - .scale(this.props.NativeDimScaling?.() || 1) + .scale(this._props.NativeDimScaling?.() || 1) .transformDirection(delta[0], delta[1]); const fullWidth = NumCast(this.layoutDoc._width); const mapWidth = fullWidth - this.sidebarWidth(); @@ -361,7 +363,7 @@ export class MapBox extends ViewBoxAnnotatableComponent UndoManager.RunInBatch(this.toggleSidebar, 'toggle sidebar map') ); }; - sidebarWidth = () => (Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100) * this.props.PanelWidth(); + sidebarWidth = () => (Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100) * this._props.PanelWidth(); /** * Handles toggle of sidebar on click the little comment button @@ -373,8 +375,8 @@ export class MapBox extends ViewBoxAnnotatableComponent @@ -406,16 +408,16 @@ export class MapBox extends ViewBoxAnnotatableComponent { - const target = DocUtils.GetNewTextDoc('Note linked to ' + this.rootDoc.title, 0, 0, 100, 100, undefined, annotationOn, undefined, 'yellow'); - FormattedTextBox.SelectOnLoad = target[Id]; + const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, undefined, annotationOn, undefined, 'yellow'); + FormattedTextBox.SetSelectOnLoad(target); return target; }; - const docView = this.props.DocumentView?.(); + const docView = this._props.DocumentView?.(); docView && DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(docView, sourceAnchorCreator, targetCreator), e.pageX, e.pageY, { dragComplete: e => { if (!e.aborted && e.annoDragData && e.annoDragData.linkSourceDoc && e.annoDragData.dropDocument && e.linkDocument) { - e.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this.props.Document; + e.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this._props.Document; e.annoDragData.linkSourceDoc.followLinkZoom = false; } }, @@ -454,15 +456,15 @@ export class MapBox extends ViewBoxAnnotatableComponent this.addDocument(doc, annotationKey); - pointerEvents = () => (this.props.isContentActive() && !MarqueeOptionsMenu.Instance.isShown() ? 'all' : 'none'); + pointerEvents = () => (this._props.isContentActive() && !MarqueeOptionsMenu.Instance.isShown() ? 'all' : 'none'); - panelWidth = () => this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1) - this.sidebarWidth(); - panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); - scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._layout_scrollTop)); - transparentFilter = () => [...this.props.childFilters(), Utils.TransparentBackgroundFilter]; - opaqueFilter = () => [...this.props.childFilters(), Utils.OpaqueBackgroundFilter]; - infoWidth = () => this.props.PanelWidth() / 5; - infoHeight = () => this.props.PanelHeight() / 5; + panelWidth = () => this._props.PanelWidth() / (this._props.NativeDimScaling?.() || 1) - this.sidebarWidth(); + panelHeight = () => this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1); + scrollXf = () => this._props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._layout_scrollTop)); + transparentFilter = () => [...this._props.childFilters(), Utils.TransparentBackgroundFilter]; + opaqueFilter = () => [...this._props.childFilters(), Utils.OpaqueBackgroundFilter]; + infoWidth = () => this._props.PanelWidth() / 5; + infoHeight = () => this._props.PanelHeight() / 5; anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick; savedAnnotations = () => this._savedAnnotations; @@ -500,7 +502,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { if (this.selectedPinOrRoute) { // // Removes filter - // Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPin.latitude, 'remove'); - // Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.longitude, 'remove'); - // Doc.setDocFilter(this.rootDoc, LinkedTo, `mapPin=${Field.toScriptString(DocCast(this.selectedPin))}`, 'remove'); - + // Doc.setDocFilter(this.Document, 'latitude', this.selectedPin.latitude, 'remove'); + // Doc.setDocFilter(this.Document, 'longitude', this.selectedPin.longitude, 'remove'); + // Doc.setDocFilter(this.Document, LinkedTo, `mapPin=${Field.toScriptString(DocCast(this.selectedPin))}`, 'remove'); // const temp = this.selectedPin; // if (!this._unmounting) { // this._bingMap.current.entities.remove(this.map_docToPinMap.get(temp)); @@ -529,11 +529,10 @@ export class MapBox extends ViewBoxAnnotatableComponent { if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) this.toggleSidebar(); return new Promise>(res => DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv))); @@ -547,9 +546,9 @@ export class MapBox extends ViewBoxAnnotatableComponent { - this.props.select(false); + this._props.select(false); this.deselectPinOrRoute(); }; /* @@ -618,8 +617,8 @@ export class MapBox extends ViewBoxAnnotatableComponent { /// this should use SELECTED pushpin for lat/long if there is a selection, otherwise CENTER const anchor = Docs.Create.ConfigDocument({ - title: 'MapAnchor:' + this.rootDoc.title, - text: StrCast(this.selectedPinOrRoute?.map) || StrCast(this.rootDoc.map) || 'map location', + title: 'MapAnchor:' + this.Document.title, + text: StrCast(this.selectedPinOrRoute?.map) || StrCast(this.Document.map) || 'map location', config_latitude: NumCast((existingPin ?? this.selectedPinOrRoute)?.latitude ?? this.dataDoc.latitude), config_longitude: NumCast((existingPin ?? this.selectedPinOrRoute)?.longitude ?? this.dataDoc.longitude), config_map_zoom: NumCast(this.dataDoc.map_zoom), @@ -627,15 +626,15 @@ export class MapBox extends ViewBoxAnnotatableComponent(); @@ -682,9 +681,9 @@ export class MapBox extends ViewBoxAnnotatableComponent { if (this.selectedPinOrRoute) { // Removes filter - Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPinOrRoute.latitude, 'remove'); - Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPinOrRoute.longitude, 'remove'); - Doc.setDocFilter(this.rootDoc, LinkedTo, `mapPin=${Field.toScriptString(DocCast(this.selectedPinOrRoute))}`, 'remove'); + Doc.setDocFilter(this.Document, 'latitude', this.selectedPinOrRoute.latitude, 'remove'); + Doc.setDocFilter(this.Document, 'longitude', this.selectedPinOrRoute.longitude, 'remove'); + Doc.setDocFilter(this.Document, LinkedTo, `mapPin=${Field.toScriptString(DocCast(this.selectedPinOrRoute))}`, 'remove'); this.removePushpinOrRoute(this.selectedPinOrRoute); } @@ -692,8 +691,6 @@ export class MapBox extends ViewBoxAnnotatableComponent { let target = document.elementFromPoint(e.x, e.y); while (target) { @@ -711,8 +708,8 @@ export class MapBox extends ViewBoxAnnotatableComponent { if (this.selectedPinOrRoute) { this._mapRef.current?.flyTo({ - center: [NumCast(this.selectedPinOrRoute.longitude), NumCast(this.selectedPinOrRoute.latitude)] - }) + center: [NumCast(this.selectedPinOrRoute.longitude), NumCast(this.selectedPinOrRoute.latitude)], + }); } // if (this.selectedPin) { // this.dataDoc.latitude = this.selectedPin.latitude; @@ -733,7 +730,6 @@ export class MapBox extends ViewBoxAnnotatableComponent { // this._bingMap.current.entities.remove(this.map_docToPinMap.get(pin)); // this.map_docToPinMap.delete(pin); @@ -780,7 +774,7 @@ export class MapBox extends ViewBoxAnnotatableComponent this.rootDoc.map, + () => this.Document.map, mapLoc => (this.bingSearchBarContents = mapLoc), { fireImmediately: true } ); @@ -805,7 +799,7 @@ export class MapBox extends ViewBoxAnnotatableComponent ({ lat: this.rootDoc.latitude, lng: this.rootDoc.longitude, zoom: this.rootDoc.map_zoom, mapType: this.rootDoc.map_type }), + () => ({ lat: this.Document.latitude, lng: this.Document.longitude, zoom: this.Document.map_zoom, mapType: this.Document.map_type }), locationObject => { // if (this._bingMap.current) try { @@ -829,25 +823,27 @@ export class MapBox extends ViewBoxAnnotatableComponent { // move event + e => { + // move event if (!dragClone) { - dragClone = this._dragRef.current?.cloneNode(true) as HTMLDivElement; // copy draggable pin + dragClone = this._dragRef.current?.cloneNode(true) as HTMLDivElement; // copy draggable pin dragClone.style.position = 'absolute'; dragClone.style.zIndex = '10000'; - DragManager.Root().appendChild(dragClone); // add clone to root + DragManager.Root().appendChild(dragClone); // add clone to root } dragClone.style.transform = `translate(${e.clientX - 15}px, ${e.clientY - 15}px)`; return false; }, - e => { // up event + e => { + // up event if (!dragClone) return; DragManager.Root().removeChild(dragClone); let target = document.elementFromPoint(e.x, e.y); // element for specified x and y coordinates while (target) { - if (target === this._ref.current) { - const cpt = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); - const x = cpt[0] - (this.props.PanelWidth() - this.sidebarWidth()) / 2; - const y = cpt[1] - 20 /* height of search bar */ - this.props.PanelHeight() / 2; + if (target === this._ref.current) { + const cpt = this._props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); + const x = cpt[0] - (this._props.PanelWidth() - this.sidebarWidth()) / 2; + const y = cpt[1] - 20 /* height of search bar */ - this._props.PanelHeight() / 2; const location = this._bingMap.current.tryPixelToLocation(new this.MicrosoftMaps.Point(x, y)); this.createPushpin(location.latitude, location.longitude); break; @@ -856,7 +852,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { - const createPin = () => this.createPushpin(this.rootDoc.latitude, this.rootDoc.longitude, this.rootDoc.map); + const createPin = () => this.createPushpin(this.Document.latitude, this.Document.longitude, this.Document.map); if (this.bingSearchBarContents) { this.bingSearch().then(createPin); } else createPin(); @@ -864,7 +860,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { - const mapRoute = Docs.Create.MapRouteDocument( - false, - [], - {title: `${origin} --> ${destination.place_name}`, routeCoordinates: JSON.stringify(coordinates)}, - ); + 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); @@ -912,43 +904,29 @@ export class MapBox extends ViewBoxAnnotatableComponent e.key === 'Enter' && this.bingSearch(); - - - - - @observable featuresFromGeocodeResults: any[] = []; - @action addMarkerForFeature = (feature: any) => { const location = feature.place_name; - if (feature.center){ + if (feature.center) { const longitude = feature.center[0]; const latitude = feature.center[1]; const wikiData = feature.properties?.wikiData; - - this.createPushpin( - latitude, - longitude, - location, - wikiData - ) - - if (this._mapRef.current){ + + this.createPushpin(latitude, longitude, location, wikiData); + + if (this._mapRef.current) { this._mapRef.current.flyTo({ - center: feature.center + center: feature.center, }); } this.featuresFromGeocodeResults = []; - } else { // TODO: handle error } - } - - + }; /** * Makes a forward geocoding API call to Mapbox to retrieve locations based on the search input @@ -956,12 +934,12 @@ export class MapBox extends ViewBoxAnnotatableComponent { const features = await MapboxApiUtility.forwardGeocodeForFeatures(searchText); - if (features && !this.isAnimating){ + if (features && !this.isAnimating) { runInAction(() => { - this.settingsOpen= false; + this.settingsOpen = false; this.featuresFromGeocodeResults = features; this.routeToAnimate = undefined; - }) + }); } // try { // const url = MAPBOX_FORWARD_GEOCODE_BASE_URL + encodeURI(searchText) +'.json' +`?access_token=${MAPBOX_ACCESS_TOKEN}`; @@ -971,34 +949,31 @@ export class MapBox extends ViewBoxAnnotatableComponent { - if (this._mapRef.current){ - const features = this._mapRef.current.queryRenderedFeatures( - e.point, { - layers: ['map-routes-layer'] - } - ); + if (this._mapRef.current) { + const features = this._mapRef.current.queryRenderedFeatures(e.point, { + layers: ['map-routes-layer'], + }); console.error(features); if (features && features.length > 0 && features[0].properties && features[0].geometry) { const geometry = features[0].geometry as LineString; const routeTitle: string = features[0].properties['routeTitle']; - const routeDoc: Doc | undefined = this.allRoutes.find((routeDoc) => routeDoc.title === routeTitle); + const routeDoc: Doc | undefined = this.allRoutes.find(routeDoc => routeDoc.title === routeTitle); this.deselectPinOrRoute(); // TODO: Also deselect route if selected - if (routeDoc){ + if (routeDoc) { this.selectedPinOrRoute = routeDoc; - Doc.setDocFilter(this.rootDoc, LinkedTo, `mapRoute=${Field.toScriptString(this.selectedPinOrRoute)}`, 'check'); + Doc.setDocFilter(this.Document, LinkedTo, `mapRoute=${Field.toScriptString(this.selectedPinOrRoute)}`, 'check'); - // TODO: Recolor route + // TODO: Recolor route MapAnchorMenu.Instance.Delete = this.deleteSelectedPinOrRoute; MapAnchorMenu.Instance.Center = this.centerOnSelectedPin; @@ -1008,9 +983,7 @@ export class MapBox extends ViewBoxAnnotatableComponent !anno.layout_unrendered) - ) + MapAnchorMenu.Instance.setAllMapboxPins(this.allAnnotations.filter(anno => !anno.layout_unrendered)); MapAnchorMenu.Instance.DisplayRoute = this.displayRoute; MapAnchorMenu.Instance.HideRoute = this.hideRoute; @@ -1025,16 +998,15 @@ export class MapBox extends ViewBoxAnnotatableComponent { e.preventDefault(); @@ -1043,13 +1015,13 @@ export class MapBox extends ViewBoxAnnotatableComponent { this.featuresFromGeocodeResults = features; - }) + }); } - // // REVERSE GEOCODE TO GET LOCATION DETAILS + // // REVERSE GEOCODE TO GET LOCATION DETAILS // try { // const url = MAPBOX_REVERSE_GEOCODE_BASE_URL + encodeURI(longitude.toString() + "," + latitude.toString()) + '.json' + // `?access_token=${MAPBOX_ACCESS_TOKEN}`; @@ -1063,9 +1035,9 @@ export class MapBox extends ViewBoxAnnotatableComponent !anno.layout_unrendered) - ) + MapAnchorMenu.Instance.setAllMapboxPins(this.allAnnotations.filter(anno => !anno.layout_unrendered)); MapAnchorMenu.Instance.DisplayRoute = this.displayRoute; MapAnchorMenu.Instance.HideRoute = this.hideRoute; @@ -1106,22 +1075,20 @@ export class MapBox extends ViewBoxAnnotatableComponent | undefined, type: TransportationType) => { - if (routeInfoMap){ + if (routeInfoMap) { const newTempRouteSource: FeatureCollection = { type: 'FeatureCollection', features: [ @@ -1130,16 +1097,16 @@ export class MapBox extends ViewBoxAnnotatableComponent { this.frameId = frameId; - } + }; - @observable + @observable animationUtility: AnimationUtility | null = null; @action setAnimationUtility = (util: AnimationUtility) => { this.animationUtility = util; - } + }; @action openAnimationPanel = (routeDoc: Doc | undefined) => { - if (routeDoc){ + if (routeDoc) { MapAnchorMenu.Instance.fadeOut(true); document.removeEventListener('pointerdown', this.tryHideMapAnchorMenu, true); 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.8240, + 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 + right: 0, }, - } + }; - @computed + @computed get preAnimationViewState() { - if (!this.isAnimating){ + if (!this.isAnimating) { return this.mapboxMapViewState; } } - - @observable + @observable isStreetViewAnimation: boolean = false; - @observable + @observable animationSpeed: AnimationSpeed = AnimationSpeed.MEDIUM; - @observable animationLineColor: string = '#ffff00'; @action - setAnimationLineColor = (color: ColorState) => { + setAnimationLineColor = (color: ColorResult) => { this.animationLineColor = color.hex; - } + }; @action updateAnimationSpeed = () => { let newAnimationSpeed: AnimationSpeed; - switch (this.animationSpeed){ + switch (this.animationSpeed) { case AnimationSpeed.SLOW: newAnimationSpeed = AnimationSpeed.MEDIUM; break; @@ -1239,63 +1204,62 @@ export class MapBox extends ViewBoxAnnotatableComponent { const newVal = !this.isStreetViewAnimation; this.isStreetViewAnimation = newVal; - if (this.animationUtility){ - this.animationUtility.updateIsStreetViewAnimation(newVal) + if (this.animationUtility) { + this.animationUtility.updateIsStreetViewAnimation(newVal); } - } + }; - @observable + @observable dynamicRouteFeature: Feature = { type: 'Feature', properties: {}, geometry: { type: 'LineString', - coordinates: [] - } + coordinates: [], + }, }; - - @observable + @observable path: turf.helpers.Feature = { type: 'Feature', geometry: { type: 'LineString', - coordinates: [] + coordinates: [], }, - properties: {} + properties: {}, }; getFeatureFromRouteDoc = (routeDoc: Doc): Feature => { @@ -1306,14 +1270,15 @@ export class MapBox extends ViewBoxAnnotatableComponent { - if (!this._mapRef.current || !this.routeToAnimate){ + if (!this._mapRef.current || !this.routeToAnimate) { return; } @@ -1322,43 +1287,32 @@ export class MapBox extends ViewBoxAnnotatableComponent { - return new Promise(async (resolve) => { + return new Promise(async resolve => { const targetLngLat = { lng: this.selectedRouteCoordinates[0][0], lat: this.selectedRouteCoordinates[0][1], }; - const animationUtil = new AnimationUtility( - targetLngLat, - this.selectedRouteCoordinates, - this.isStreetViewAnimation, - this.animationSpeed, - this.showTerrain, - this._mapRef.current - ); + const animationUtil = new AnimationUtility(targetLngLat, this.selectedRouteCoordinates, this.isStreetViewAnimation, this.animationSpeed, this.showTerrain, this._mapRef.current); runInAction(() => { this.setAnimationUtility(animationUtil); - }) - + }); const updateFrameId = (newFrameId: number) => { this.setFrameId(newFrameId); - } + }; - const updateAnimationPhase = ( - newAnimationPhase: number, - ) => { + const updateAnimationPhase = (newAnimationPhase: number) => { this.setAnimationPhase(newAnimationPhase); }; - - if (status !== AnimationStatus.RESUME) { + if (status !== AnimationStatus.RESUME) { const result = await animationUtil.flyInAndRotate({ map: this._mapRef.current!, // targetLngLat, @@ -1372,18 +1326,17 @@ export class MapBox extends ViewBoxAnnotatableComponent { this.finishedFlyTo = true; - }) + }); // follow the path while slowly rotating the camera, passing in the camera bearing and altitude from the previous animation await animationUtil.animatePath({ - map: this._mapRef.current!, + map: this._mapRef.current!, // path: this.path, // startBearing: -20, // startAltitude: this.isStreetViewAnimation ? 80 : 12000, @@ -1392,43 +1345,39 @@ export class MapBox extends ViewBoxAnnotatableComponent { this.isStreetViewAnimation = false; resolve(); }, 10000); }); - - }) - - - } - + }); + }; - @action + @action pauseAnimation = () => { - if (this.frameId && this.animationPhase > 0){ + if (this.frameId && this.animationPhase > 0) { window.cancelAnimationFrame(this.frameId); this.frameId = null; this.isAnimating = false; } - } + }; @action stopAnimation = (close: boolean) => { - if (this.frameId){ + if (this.frameId) { window.cancelAnimationFrame(this.frameId); } this.animationPhase = 0; @@ -1441,22 +1390,18 @@ export class MapBox extends ViewBoxAnnotatableComponent { - - } + exportAnimationToVideo = () => {}; getRouteAnimationOptions = (): JSX.Element => { return ( <> - { if (this.isAnimating && this.finishedFlyTo) { @@ -1467,87 +1412,57 @@ export class MapBox extends ViewBoxAnnotatableComponent - : - - } - color='black' - size={Size.MEDIUM} - /> - {this.isAnimating && this.finishedFlyTo && - { - this.stopAnimation(false); - this.playAnimation(AnimationStatus.START) - }} - icon={} - color='black' - size={Size.MEDIUM} - /> - - } - this.stopAnimation(true)} - icon={} - color='black' + icon={this.isAnimating && this.finishedFlyTo ? : } + color="black" size={Size.MEDIUM} /> + {this.isAnimating && this.finishedFlyTo && ( + { + this.stopAnimation(false); + this.playAnimation(AnimationStatus.START); + }} + icon={} + color="black" + size={Size.MEDIUM} + /> + )} + this.stopAnimation(true)} icon={} color="black" size={Size.MEDIUM} /> <> -
+
|
- } - /> -
|
- } /> -
|
-
Select Line Color:
- this.setAnimationLineColor(color)} - /> +
|
+ +
|
+
Select Line Color:
+ this.setAnimationLineColor(color)} />
- + - ) - } + ); + }; @action hideRoute = () => { this.temporaryRouteSource = { type: 'FeatureCollection', - features: [] - } - } - + features: [], + }; + }; - @observable + @observable settingsOpen: boolean = false; - @observable - mapStyle: string = 'mapbox://styles/mapbox/streets-v12' + @observable + mapStyle: string = 'mapbox://styles/mapbox/streets-v12'; @observable showTerrain: boolean = true; @@ -1558,103 +1473,94 @@ export class MapBox extends ViewBoxAnnotatableComponent) => { this.dataDoc.map_style = `mapbox://styles/mapbox/${e.target.value}`; // this.mapStyle = `mapbox://styles/mapbox/${e.target.value}` - } + }; - @action + @action onBearingChange = (e: React.ChangeEvent) => { const bearing = parseInt(e.target.value); - if (!isNaN(bearing) && this._mapRef.current){ + if (!isNaN(bearing) && this._mapRef.current) { 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 - } + bearing: fixedBearing, + }; } - } + }; - @action + @action onPitchChange = (e: React.ChangeEvent) => { const pitch = parseInt(e.target.value); - if (!isNaN(pitch) && this._mapRef.current){ + if (!isNaN(pitch) && this._mapRef.current) { 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 - } + pitch: fixedPitch, + }; } - } + }; - @action + @action onZoomChange = (e: React.ChangeEvent) => { const zoom = parseInt(e.target.value); - if (!isNaN(zoom) && this._mapRef.current){ + if (!isNaN(zoom) && this._mapRef.current) { 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 - } + zoom: fixedZoom, + }; } - } + }; @action onStepZoomChange = (increment: boolean) => { if (this._mapRef.current) { let newZoom: number; if (increment) { - console.log('inc') + console.log('inc'); newZoom = this.mapboxMapViewState.zoom + 1; - } else { - console.log('dec') + console.log('dec'); newZoom = 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) - } + 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; - } + }; @action toggleShowTerrain = () => { this.showTerrain = !this.showTerrain; - } + }; getMarkerIcon = (pinDoc: Doc): JSX.Element | null => { const markerType = StrCast(pinDoc.markerType); const markerColor = StrCast(pinDoc.markerColor); return MarkerIcons.getFontAwesomeIcon(markerType, '2x', markerColor) ?? null; - - } - - - - - + }; static _firstRender = true; static _rerenderDelay = 500; @@ -1662,7 +1568,7 @@ export class MapBox extends ViewBoxAnnotatableComponent string[]) => null; return ( @@ -1687,108 +1593,76 @@ export class MapBox extends ViewBoxAnnotatableComponent { e.button === 0 && !e.ctrlKey && e.stopPropagation(); }} - style={{ transformOrigin: "top left", transform: `scale(${scale})`, width: `${100 / scale}%`, height: `${100 / scale}%`, pointerEvents: this.pointerEvents() }}> + style={{ pointerEvents: this.pointerEvents() }}>
{renderAnnotations(this.transparentFilter)}
{renderAnnotations(this.opaqueFilter)} - {SnappingManager.GetIsDragging() ? null : renderAnnotations()} - {!this.routeToAnimate && + {SnappingManager.IsDragging ? null : renderAnnotations()} + {!this.routeToAnimate && (
- this.handleSearchChange(e.target.value)} - /> - } - type={Type.TERT} - onClick={(e) => this.toggleSettings()} - - /> -
- } - {this.settingsOpen && !this.routeToAnimate && -
-
-
- Map Style: -
+ this.handleSearchChange(e.target.value)} /> + } type={Type.TERT} onClick={e => this.toggleSettings()} /> +
+ )} + {this.settingsOpen && !this.routeToAnimate && ( +
+
+
Map Style:
-
+
Bearing:
- +
-
+
Pitch:
- +
-
+
Zoom:
- +
-
+
Show terrain:
- +
- } - {this.routeToAnimate && -
-
- {StrCast(this.routeToAnimate.title)} -
-
- {this.getRouteAnimationOptions()} -
+ )} + {this.routeToAnimate && ( +
+
{StrCast(this.routeToAnimate.title)}
+
{this.getRouteAnimationOptions()}
- } + )} {this.featuresFromGeocodeResults.length > 0 && ( -
+

Choose a location for your pin:

{this.featuresFromGeocodeResults .filter(feature => feature.place_name) .map((feature, idx) => ( -
{ - this.handleSearchChange(""); - this.addMarkerForFeature(feature); - }} - > -
- {feature.place_name} +
{ + this.handleSearchChange(''); + this.addMarkerForFeature(feature); + }}> +
{feature.place_name}
-
- ))} + ))} - -
+
)} {/*
- - - - - {!this.isAnimating && this.animationPhase == 0 && - - } - {this.routeToAnimate && (this.isAnimating || this.animationPhase > 0) && + terrain={this.showTerrain ? { source: 'mapbox-dem', exaggeration: 2.0 } : undefined}> + + + + + {!this.isAnimating && this.animationPhase == 0 && } + {this.routeToAnimate && (this.isAnimating || this.animationPhase > 0) && ( <> - {!this.isStreetViewAnimation && + {!this.isStreetViewAnimation && ( <> - - + - } - - - - - + + + + - - - - - } - + )} <> - {!this.isAnimating && this.animationPhase == 0 && this.allPushpins - // .filter(anno => !anno.layout_unrendered) - .map((pushpin, idx) => ( - ) => this.handleMarkerClick(e, pushpin)} - > - {this.getMarkerIcon(pushpin)} - - ))} + {!this.isAnimating && + this.animationPhase == 0 && + this.allPushpins + // .filter(anno => !anno.layout_unrendered) + .map((pushpin, idx) => ( + ) => this.handleMarkerClick(e, pushpin)}> + {this.getMarkerIcon(pushpin)} + + ))} - + {/* {this.mapMarkers.length > 0 && this.mapMarkers.map((marker, idx) => ( ))} */} - @@ -1935,8 +1791,8 @@ export class MapBox extends ViewBoxAnnotatableComponent ( */} {/* )} - /> */} - {/* */ +} +{ + /* typeof newText === 'string' && this.handleSearchChange(newText)} // onEnter={e => this.bingSearch()} @@ -2024,8 +1883,10 @@ export class MapBox extends ViewBoxAnnotatableComponent */} - {/* */ +} +{ + /*
*/ +} -- cgit v1.2.3-70-g09d2