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.tsx1228
1 files changed, 750 insertions, 478 deletions
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index 8b5858e28..724c1a770 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -3,66 +3,72 @@ 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, makeObservable, flow, toJS } from 'mobx';
+import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, flow, toJS, autorun} from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, 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 { DocumentType } from '../../../documents/DocumentTypes';
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 { UndoManager, undoable } from '../../../util/UndoManager';
-import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocComponent';
-import { SidebarAnnos } from '../../SidebarAnnos';
+import { undoable, UndoManager } from '../../../util/UndoManager';
import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm';
+import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocComponent';
import { Colors } from '../../global/globalEnums';
+import { SidebarAnnos } from '../../SidebarAnnos';
import { DocumentView } from '../DocumentView';
import { FieldView, FieldViewProps } from '../FieldView';
import { FormattedTextBox } from '../formattedText/FormattedTextBox';
import { PinProps, PresBox } from '../trails';
import { MapAnchorMenu } from './MapAnchorMenu';
-import {
+import * as HME from "h264-mp4-encoder";
+import {simd} from 'wasm-feature-detect';
+
+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';
+ Layer} from 'react-map-gl';
+import MapboxGeocoder, {GeocoderOptions} from '@mapbox/mapbox-gl-geocoder';
+import debounce from 'debounce';
import './MapBox.scss';
import { NumberLiteralType } from 'typescript';
// import { GeocoderControl } from './GeocoderControl';
-import mapboxgl, { LngLat, LngLatBoundsLike, 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';
-import { IconLookup, faCircleXmark, faFileExport, faGear, faPause, faPlay, faRotate } from '@fortawesome/free-solid-svg-icons';
+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 * 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';
// amongus
/**
@@ -85,24 +91,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<GeocoderOptions, 'accessToken' | 'mapboxgl' | 'marker'> & {
-// mapboxAccessToken: string;
-// marker?: Omit<MarkerProps, 'longitude' | 'latitude'>;
-// position: ControlPosition;
+export type GeocoderControlProps = Omit<GeocoderOptions, 'accessToken' | 'mapboxgl' | 'marker'> & {
+ mapboxAccessToken: string,
+ marker?: Omit<MarkerProps, 'longitude' | 'latitude'>;
+ position: ControlPosition;
-// onResult: (...args: any[]) => void;
-// };
+ 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
@@ -130,13 +136,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
private _ref: React.RefObject<HTMLDivElement> = React.createRef();
private _mapRef: React.RefObject<MapRef> = React.createRef();
private _disposers: { [key: string]: IReactionDisposer } = {};
-
- constructor(props: any) {
- super(props);
- makeObservable(this);
- }
-
- _unmounting = false;
+ private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void);
@observable private _savedAnnotations = new ObservableMap<number, HTMLDivElement[]>();
@computed get allSidebarDocs() {
@@ -157,20 +157,23 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
const originalCoordinates: Position[] = JSON.parse(StrCast(this.routeToAnimate.routeCoordinates));
// const index = Math.floor(this.animationPhase * originalCoordinates.length);
const index = this.animationPhase * (originalCoordinates.length - 1); // Calculate the fractional index
+ console.log("Animation phase", this.animationPhase);
const startIndex = Math.floor(index);
const endIndex = Math.ceil(index);
+ let feature: Feature<Geometry, GeoJsonProperties>;
+ let geometry: LineString;
if (startIndex === endIndex) {
// AnimationPhase is at a whole number (no interpolation needed)
const coordinates = [originalCoordinates[startIndex]];
- const geometry: LineString = {
+ geometry = {
type: 'LineString',
coordinates,
};
- return {
+ feature = {
type: 'Feature',
properties: {
- routeTitle: StrCast(this.routeToAnimate.title),
+ 'routeTitle': StrCast(this.routeToAnimate.title)
},
geometry: geometry,
};
@@ -180,36 +183,55 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
const endCoord = originalCoordinates[endIndex];
const fraction = index - startIndex;
- // Interpolate the coordinates
- const interpolatedCoord = [startCoord[0] + fraction * (endCoord[0] - startCoord[0]), startCoord[1] + fraction * (endCoord[1] - startCoord[1])];
+ const interpolator = d3.interpolateArray(startCoord, endCoord);
+ const interpolatedCoord = interpolator(fraction);
+
const coordinates = originalCoordinates.slice(0, startIndex + 1).concat([interpolatedCoord]);
- const geometry: LineString = {
+ geometry = {
type: 'LineString',
coordinates,
};
- return {
+ feature = {
type: 'Feature',
properties: {
- routeTitle: StrCast(this.routeToAnimate.title),
+ 'routeTitle': StrCast(this.routeToAnimate.title)
},
geometry: geometry,
};
}
+
+ autorun(() => {
+ const animationUtil = this.animationUtility;
+ const concattedCoordinates = geometry.coordinates.concat(originalCoordinates.slice(endIndex));
+ const newFeature: Feature<LineString, turf.Properties> = {
+ type: 'Feature',
+ properties: {},
+ geometry: {
+ type: 'LineString',
+ coordinates: concattedCoordinates
+ }
+ }
+ if (animationUtil){
+ animationUtil.setPath(newFeature)
+ }
+ })
+ return feature;
}
+ console.log("ERROR");
return {
type: 'Feature',
properties: {},
geometry: {
type: 'LineString',
- coordinates: [],
+ coordinates: []
},
};
}
@computed get selectedRouteCoordinates(): Position[] {
let coordinates: Position[] = [];
- if (this.routeToAnimate?.routeCoordinates) {
+ if (this.routeToAnimate?.routeCoordinates){
coordinates = JSON.parse(StrCast(this.routeToAnimate.routeCoordinates));
}
return coordinates;
@@ -225,8 +247,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
return {
type: 'Feature',
properties: {
- routeTitle: routeDoc.title,
- },
+ 'routeTitle': routeDoc.title},
geometry: geometry,
};
});
@@ -244,7 +265,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
return StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%');
}
@computed get sidebarColor() {
- return StrCast(this.layoutDoc.sidebar_color, StrCast(this.layoutDoc[this._props.fieldKey + '_backgroundColor'], '#e4e4e4'));
+ return StrCast(this.layoutDoc.sidebar_color, StrCast(this.layoutDoc[this.props.fieldKey + '_backgroundColor'], '#e4e4e4'));
}
@computed get SidebarKey() {
return this.fieldKey + '_sidebar';
@@ -252,9 +273,12 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
componentDidMount() {
this._unmounting = false;
- this._props.setContentView?.(this);
+ this.props.setContentView?.(this);
+
}
+
+ _unmounting = false;
componentWillUnmount(): void {
this._unmounting = true;
this.deselectPinOrRoute();
@@ -316,9 +340,9 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
e,
(e, down, delta) =>
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();
@@ -337,7 +361,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
() => 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
@@ -349,8 +373,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
key="sidebar"
title="Toggle Sidebar"
style={{
- display: !this._props.isContentActive() ? 'none' : undefined,
- top: StrCast(this.layoutDoc._layout_showTitle) === 'title' ? 20 : 5,
+ display: !this.props.isContentActive() ? 'none' : undefined,
+ top: StrCast(this.rootDoc._layout_showTitle) === 'title' ? 20 : 5,
backgroundColor: this.SidebarShown ? Colors.MEDIUM_BLUE : Colors.BLACK,
}}
onPointerDown={this.sidebarBtnDown}>
@@ -382,16 +406,16 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
});
const targetCreator = (annotationOn: Doc | undefined) => {
- const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, undefined, annotationOn, undefined, 'yellow');
- FormattedTextBox.SetSelectOnLoad(target);
+ const target = DocUtils.GetNewTextDoc('Note linked to ' + this.rootDoc.title, 0, 0, 100, 100, undefined, annotationOn, undefined, 'yellow');
+ FormattedTextBox.SelectOnLoad = target[Id];
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.Document;
+ e.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this.props.Document;
e.annoDragData.linkSourceDoc.followLinkZoom = false;
}
},
@@ -426,17 +450,19 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
return false;
};
+ setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void) => (this._setPreviewCursor = func);
+
addDocumentWrapper = (doc: Doc | Doc[], annotationKey?: string) => 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;
@@ -474,7 +500,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
};
@observable
- bingSearchBarContents: any = this.dataDoc.map; // For Bing Maps: The contents of the Bing search bar (string)
+ bingSearchBarContents: any = this.rootDoc.map; // For Bing Maps: The contents of the Bing search bar (string)
geoDataRequestOptions = {
entityType: 'PopulatedPlace',
@@ -483,13 +509,15 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
// The pin that is selected
@observable selectedPinOrRoute: Doc | undefined;
+
@action
deselectPinOrRoute = () => {
if (this.selectedPinOrRoute) {
// // Removes filter
- // 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');
+ // 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');
+
// const temp = this.selectedPin;
// if (!this._unmounting) {
// this._bingMap.current.entities.remove(this.map_docToPinMap.get(temp));
@@ -501,10 +529,11 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
// }
// this.map_docToPinMap.set(temp, newpin);
// this.selectedPin = undefined;
- // this.bingSearchBarContents = this.Document.map;
+ // this.bingSearchBarContents = this.rootDoc.map;
}
};
+
getView = async (doc: Doc) => {
if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) this.toggleSidebar();
return new Promise<Opt<DocumentView>>(res => DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv)));
@@ -518,9 +547,9 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this.selectedPinOrRoute = pinDoc;
this.bingSearchBarContents = pinDoc.map;
- // Doc.setDocFilter(this.Document, 'latitude', this.selectedPin.latitude, 'match');
- // Doc.setDocFilter(this.Document, 'longitude', this.selectedPin.longitude, 'match');
- Doc.setDocFilter(this.Document, LinkedTo, `mapPin=${Field.toScriptString(this.selectedPinOrRoute)}`, 'check');
+ // Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPin.latitude, 'match');
+ // Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.longitude, 'match');
+ Doc.setDocFilter(this.rootDoc, LinkedTo, `mapPin=${Field.toScriptString(this.selectedPinOrRoute)}`, 'check');
this.recolorPin(this.selectedPinOrRoute, 'green');
@@ -530,9 +559,9 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
MapAnchorMenu.Instance.StartDrag = this.startAnchorDrag;
const point = this._bingMap.current.tryLocationToPixel(new this.MicrosoftMaps.Location(this.selectedPinOrRoute.latitude, this.selectedPinOrRoute.longitude));
- const x = point.x + (this._props.PanelWidth() - this.sidebarWidth()) / 2;
- const y = point.y + this._props.PanelHeight() / 2 + 32;
- const cpt = this._props.ScreenToLocalTransform().inverse().transformPoint(x, y);
+ const x = point.x + (this.props.PanelWidth() - this.sidebarWidth()) / 2;
+ const y = point.y + this.props.PanelHeight() / 2 + 32;
+ const cpt = this.props.ScreenToLocalTransform().inverse().transformPoint(x, y);
MapAnchorMenu.Instance.jumpTo(cpt[0], cpt[1], true);
document.addEventListener('pointerdown', this.tryHideMapAnchorMenu, true);
@@ -543,7 +572,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
*/
@action
mapOnClick = (e: { location: { latitude: any; longitude: any } }) => {
- this._props.select(false);
+ this.props.select(false);
this.deselectPinOrRoute();
};
/*
@@ -586,28 +615,27 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
/*
* Returns doc w/ relevant info
*/
-
getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps, existingPin?: Doc) => {
/// this should use SELECTED pushpin for lat/long if there is a selection, otherwise CENTER
const anchor = Docs.Create.ConfigDocument({
- title: 'MapAnchor:' + this.Document.title,
- text: StrCast(this.selectedPinOrRoute?.map) || StrCast(this.Document.map) || 'map location',
+ title: 'MapAnchor:' + this.rootDoc.title,
+ text: StrCast(this.selectedPinOrRoute?.map) || StrCast(this.rootDoc.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),
- config_map_type: StrCast(this.dataDoc.map_type),
+ // config_map_type: StrCast(this.dataDoc.map_type),
config_map: StrCast((existingPin ?? this.selectedPinOrRoute)?.map) || StrCast(this.dataDoc.map),
layout_unrendered: true,
mapPin: existingPin ?? this.selectedPinOrRoute,
- annotationOn: this.Document,
+ annotationOn: this.rootDoc,
});
if (anchor) {
if (!addAsAnnotation) anchor.backgroundColor = 'transparent';
addAsAnnotation && this.addDocument(anchor);
- PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), map: true } }, this.Document);
+ PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), map: true } }, this.rootDoc);
return anchor;
}
- return this.Document;
+ return this.rootDoc;
};
map_docToPinMap = new Map<Doc, any>();
@@ -654,9 +682,9 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
deleteSelectedPinOrRoute = undoable(() => {
if (this.selectedPinOrRoute) {
// Removes filter
- 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');
+ 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');
this.removePushpinOrRoute(this.selectedPinOrRoute);
}
@@ -664,6 +692,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
document.removeEventListener('pointerdown', this.tryHideMapAnchorMenu, true);
}, 'delete pin');
+
+
tryHideMapAnchorMenu = (e: PointerEvent) => {
let target = document.elementFromPoint(e.x, e.y);
while (target) {
@@ -681,8 +711,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
centerOnSelectedPin = () => {
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;
@@ -703,6 +733,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
mapTypeId: 'grayscale',
};
+
/**
* Map options
*/
@@ -721,6 +752,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
},
};
+
+
recolorPin = (pin: Doc, color?: string) => {
// this._bingMap.current.entities.remove(this.map_docToPinMap.get(pin));
// this.map_docToPinMap.delete(pin);
@@ -735,7 +768,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
* Initializes starting values
*/
@observable _mapReady = false;
-
@action
bingMapReady = (map: any) => {
this._mapReady = true;
@@ -748,7 +780,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this.MicrosoftMaps.Events.addHandler(this._bingMap.current, 'maptypechanged', undoable(this.updateMapType, 'Map ViewType Change'));
this._disposers.mapLocation = reaction(
- () => this.dataDoc.map,
+ () => this.rootDoc.map,
mapLoc => (this.bingSearchBarContents = mapLoc),
{ fireImmediately: true }
);
@@ -773,7 +805,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
);
this._disposers.location = reaction(
- () => ({ lat: this.dataDoc.latitude, lng: this.dataDoc.longitude, zoom: this.dataDoc.map_zoom, mapType: this.dataDoc.map_type }),
+ () => ({ lat: this.rootDoc.latitude, lng: this.rootDoc.longitude, zoom: this.rootDoc.map_zoom, mapType: this.rootDoc.map_type }),
locationObject => {
// if (this._bingMap.current)
try {
@@ -797,27 +829,25 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
setupMoveUpEvents(
e,
e,
- e => {
- // 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;
@@ -826,7 +856,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}
},
e => {
- const createPin = () => this.createPushpin(this.dataDoc.latitude, this.dataDoc.longitude, this.dataDoc.map);
+ const createPin = () => this.createPushpin(this.rootDoc.latitude, this.rootDoc.longitude, this.rootDoc.map);
if (this.bingSearchBarContents) {
this.bingSearch().then(createPin);
} else createPin();
@@ -834,7 +864,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
);
};
- // incrementer: number = 0;
+ // incrementer: number = 0;
/*
* Creates Pushpin doc and adds it to the list of annotations
*/
@@ -847,13 +877,13 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
false,
[],
{
- title: location ?? `lat=${NumCast(latitude)},lng=${NumCast(longitude)}`,
- map: location,
- description: '',
+ title: location ?? `lat=${NumCast(latitude)},lng=${NumCast(longitude)}`,
+ map: location,
+ description: "",
wikiData: wikiData,
markerType: 'MAP_PIN',
- markerColor: '#ff5722',
- }
+ markerColor: '#ff5722'
+ },
// { title: map ?? `lat=${latitude},lng=${longitude}`, map: map },
// ,'pushpinIDamongus'+ this.incrementer++
);
@@ -866,7 +896,11 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
@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) });
+ 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);
@@ -878,29 +912,43 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
searchbarKeyDown = (e: any) => 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
@@ -908,12 +956,12 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
*/
handleSearchChange = async (searchText: string) => {
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}`;
@@ -923,31 +971,34 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
// this.featuresFromGeocodeResults = data.features;
// })
// } catch (error: any){
- // // TODO: handle error in better way
+ // // TODO: handle error in better way
// console.log(error);
// }
- };
+ }
// @action
// debouncedCall = React.useCallback(debounce(this.debouncedOnSearchBarChange, 300), []);
+
@action
handleMapClick = (e: MapLayerMouseEvent) => {
- 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.Document, LinkedTo, `mapRoute=${Field.toScriptString(this.selectedPinOrRoute)}`, 'check');
+ Doc.setDocFilter(this.rootDoc, LinkedTo, `mapRoute=${Field.toScriptString(this.selectedPinOrRoute)}`, 'check');
- // TODO: Recolor route
+ // TODO: Recolor route
MapAnchorMenu.Instance.Delete = this.deleteSelectedPinOrRoute;
MapAnchorMenu.Instance.Center = this.centerOnSelectedPin;
@@ -957,7 +1008,9 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
MapAnchorMenu.Instance.setRouteDoc(routeDoc);
// TODO: Subject to change
- MapAnchorMenu.Instance.setAllMapboxPins(this.allAnnotations.filter(anno => !anno.layout_unrendered));
+ MapAnchorMenu.Instance.setAllMapboxPins(
+ this.allAnnotations.filter(anno => !anno.layout_unrendered)
+ )
MapAnchorMenu.Instance.DisplayRoute = this.displayRoute;
MapAnchorMenu.Instance.HideRoute = this.hideRoute;
@@ -972,15 +1025,16 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
MapAnchorMenu.Instance.jumpTo(e.originalEvent.clientX, e.originalEvent.clientY, true);
document.addEventListener('pointerdown', this.tryHideMapAnchorMenu, true);
- }
+ }
}
}
- };
+ }
+
/**
* Makes a reverse geocoding API call to retrieve features corresponding to a map click (based on longitude
- * and latitude). Sets the search results accordingly.
- * @param e
+ * and latitude). Sets the search results accordingly.
+ * @param e
*/
handleMapDblClick = async (e: MapLayerMouseEvent) => {
e.preventDefault();
@@ -989,13 +1043,13 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
const latitude: number = lngLat.lat;
const features = await MapboxApiUtility.reverseGeocodeForFeatures(longitude, latitude);
- if (features) {
+ if (features){
runInAction(() => {
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}`;
@@ -1009,9 +1063,9 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
// // TODO: handle error in better way
// console.log(error);
// }
- };
+ }
- @observable
+ @observable
currentPopup: PopupInfo | undefined = undefined;
@action
@@ -1021,20 +1075,23 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this.selectedPinOrRoute = pinDoc;
// this.bingSearchBarContents = pinDoc.map;
- // Doc.setDocFilter(this.Document, 'latitude', this.selectedPin.latitude, 'match');
- // Doc.setDocFilter(this.Document, 'longitude', this.selectedPin.longitude, 'match');
- Doc.setDocFilter(this.Document, LinkedTo, `mapPin=${Field.toScriptString(this.selectedPinOrRoute)}`, 'check');
+ // Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPin.latitude, 'match');
+ // Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.longitude, 'match');
+ Doc.setDocFilter(this.rootDoc, LinkedTo, `mapPin=${Field.toScriptString(this.selectedPinOrRoute)}`, 'check');
this.recolorPin(this.selectedPinOrRoute, 'green'); // TODO: check this method
-
+
+
MapAnchorMenu.Instance.Delete = this.deleteSelectedPinOrRoute;
MapAnchorMenu.Instance.Center = this.centerOnSelectedPin;
MapAnchorMenu.Instance.OnClick = this.createNoteAnnotation;
MapAnchorMenu.Instance.StartDrag = this.startAnchorDrag;
- // pass in the pinDoc
+ // pass in the pinDoc
MapAnchorMenu.Instance.setPinDoc(pinDoc);
- MapAnchorMenu.Instance.setAllMapboxPins(this.allAnnotations.filter(anno => !anno.layout_unrendered));
+ MapAnchorMenu.Instance.setAllMapboxPins(
+ this.allAnnotations.filter(anno => !anno.layout_unrendered)
+ )
MapAnchorMenu.Instance.DisplayRoute = this.displayRoute;
MapAnchorMenu.Instance.HideRoute = this.hideRoute;
@@ -1043,20 +1100,28 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
MapAnchorMenu.Instance.setMenuType('standard');
+ // MapAnchorMenu.Instance.jumpTo(NumCast(pinDoc.longitude), NumCast(pinDoc.latitude)-3, true);
+
MapAnchorMenu.Instance.jumpTo(e.originalEvent.clientX, e.originalEvent.clientY, true);
document.addEventListener('pointerdown', this.tryHideMapAnchorMenu, true);
+
+
+ // this._mapRef.current.flyTo({
+ // center: [NumCast(pinDoc.longitude), NumCast(pinDoc.latitude)-3]
+ // })
+
};
@observable
temporaryRouteSource: FeatureCollection = {
type: 'FeatureCollection',
- features: [],
- };
+ features: []
+ }
@action
displayRoute = (routeInfoMap: Record<TransportationType, any> | undefined, type: TransportationType) => {
- if (routeInfoMap) {
+ if (routeInfoMap){
const newTempRouteSource: FeatureCollection = {
type: 'FeatureCollection',
features: [
@@ -1065,30 +1130,27 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
properties: {},
geometry: {
type: 'LineString',
- coordinates: routeInfoMap[type].coordinates,
- },
- },
- ],
- };
- // TODO: Create pin for destination
- // TODO: Fly to point where full route will be shown
+ coordinates: routeInfoMap[type].coordinates
+ }
+ }
+ ]
+ }
+ // TODO: Create pin for destination
+ // TODO: Fly to point where full route will be shown
this.temporaryRouteSource = newTempRouteSource;
}
- };
+ }
@observable
isAnimating: boolean = false;
@observable
- isPaused: boolean = false;
-
- @observable
routeToAnimate: Doc | undefined = undefined;
- @observable
+ @observable
animationPhase: number = 0;
- @observable
+ @observable
finishedFlyTo: boolean = false;
@action
@@ -1096,103 +1158,144 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this.animationPhase = newValue;
};
- @observable
+ @observable
frameId: number | null = null;
@action
setFrameId = (frameId: number) => {
this.frameId = frameId;
- };
+ }
+
+ @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
- animationDuration = 40000;
+ 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,
+ 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
+ },
+ }
- @observable
- animationAltitude = 12800;
+ @computed
+ get preAnimationViewState() {
+ if (!this.isAnimating){
+ return this.mapboxMapViewState;
+ }
+ }
- @observable
- pathDistance = 0;
- @observable
+ @observable
isStreetViewAnimation: boolean = false;
- @observable
+ @observable
animationSpeed: AnimationSpeed = AnimationSpeed.MEDIUM;
+
+ @observable
+ animationLineColor: string = '#ffff00';
+
+ @action
+ setAnimationLineColor = (color: ColorState) => {
+ this.animationLineColor = color.hex;
+ }
+
@action
updateAnimationSpeed = () => {
- switch (this.animationSpeed) {
+ let newAnimationSpeed: AnimationSpeed;
+ switch (this.animationSpeed){
case AnimationSpeed.SLOW:
- this.animationSpeed = AnimationSpeed.MEDIUM;
+ newAnimationSpeed = AnimationSpeed.MEDIUM;
break;
case AnimationSpeed.MEDIUM:
- this.animationSpeed = AnimationSpeed.FAST;
+ newAnimationSpeed = AnimationSpeed.FAST;
break;
case AnimationSpeed.FAST:
- this.animationSpeed = AnimationSpeed.SLOW;
+ newAnimationSpeed = AnimationSpeed.SLOW;
break;
default:
- this.animationSpeed = AnimationSpeed.MEDIUM;
+ newAnimationSpeed = AnimationSpeed.MEDIUM;
break;
}
- };
+ this.animationSpeed = newAnimationSpeed;
+ if (this.animationUtility){
+ this.animationUtility.updateAnimationSpeed(newAnimationSpeed);
+ }
+ }
@computed get animationSpeedTooltipText(): string {
switch (this.animationSpeed) {
- case AnimationSpeed.SLOW:
- return '1x speed';
- case AnimationSpeed.MEDIUM:
- return '2x speed';
- case AnimationSpeed.FAST:
- return '3x speed';
- default:
- return '2x speed';
+ case AnimationSpeed.SLOW:
+ return '1x speed';
+ case AnimationSpeed.MEDIUM:
+ return '2x speed';
+ case AnimationSpeed.FAST:
+ return '3x speed';
+ default:
+ return '2x speed';
}
}
- @computed get animationSpeedIcon(): JSX.Element {
+ @computed get animationSpeedIcon(): JSX.Element{
switch (this.animationSpeed) {
case AnimationSpeed.SLOW:
- return slowSpeedIcon;
+ return slowSpeedIcon;
case AnimationSpeed.MEDIUM:
- return mediumSpeedIcon;
+ return mediumSpeedIcon;
case AnimationSpeed.FAST:
- return fastSpeedIcon;
+ return fastSpeedIcon;
default:
- return mediumSpeedIcon;
- }
+ return mediumSpeedIcon;
+ }
}
@action
toggleIsStreetViewAnimation = () => {
- this.isStreetViewAnimation = !this.isStreetViewAnimation;
- };
+ const newVal = !this.isStreetViewAnimation;
+ this.isStreetViewAnimation = newVal;
+ if (this.animationUtility){
+ this.animationUtility.updateIsStreetViewAnimation(newVal)
+ }
+ }
- @observable
+ @observable
dynamicRouteFeature: Feature<Geometry, GeoJsonProperties> = {
type: 'Feature',
properties: {},
geometry: {
type: 'LineString',
- coordinates: [],
- },
+ coordinates: []
+ }
};
- @observable
+
+ @observable
path: turf.helpers.Feature<turf.helpers.LineString, turf.helpers.Properties> = {
type: 'Feature',
geometry: {
type: 'LineString',
- coordinates: [],
+ coordinates: []
},
- properties: {},
+ properties: {}
};
getFeatureFromRouteDoc = (routeDoc: Doc): Feature<Geometry, GeoJsonProperties> => {
@@ -1203,137 +1306,157 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
return {
type: 'Feature',
properties: {
- routeTitle: routeDoc.title,
- },
+ 'routeTitle': routeDoc.title},
geometry: geometry,
};
- };
+ }
- @action
+ @action
playAnimation = (status: AnimationStatus) => {
- if (!this._mapRef.current || !this.routeToAnimate) {
+ if (!this._mapRef.current || !this.routeToAnimate){
return;
}
- if (this.isAnimating) {
- return;
- }
this.animationPhase = status === AnimationStatus.RESUME ? this.animationPhase : 0;
this.frameId = AnimationStatus.RESUME ? this.frameId : null;
this.finishedFlyTo = AnimationStatus.RESUME ? this.finishedFlyTo : false;
const path = turf.lineString(this.selectedRouteCoordinates);
-
+
this.settingsOpen = false;
this.path = path;
- this.pathDistance = turf.lineDistance(path);
this.isAnimating = true;
+
runInAction(() => {
- return new Promise<void>(async resolve => {
- let animationUtil;
- try {
- const targetLngLat = {
- lng: this.selectedRouteCoordinates[0][0],
- lat: this.selectedRouteCoordinates[0][1],
- };
-
- animationUtil = new AnimationUtility(targetLngLat, this.selectedRouteCoordinates, this.isStreetViewAnimation, this.animationSpeed);
-
- const updateFrameId = (newFrameId: number) => {
- this.setFrameId(newFrameId);
- };
-
- const updateAnimationPhase = (newAnimationPhase: number) => {
- this.setAnimationPhase(newAnimationPhase);
- };
-
- if (status !== AnimationStatus.RESUME) {
- const result = await animationUtil.flyInAndRotate({
- map: this._mapRef.current!,
- // targetLngLat,
- // duration 3000
- // startAltitude: 3000000,
- // endAltitude: this.isStreetViewAnimation ? 80 : 12000,
- // startBearing: 0,
- // endBearing: -20,
- // startPitch: 40,
- // endPitch: this.isStreetViewAnimation ? 80 : 50,
- updateFrameId,
- });
+ return new Promise<void>(async (resolve) => {
+ const targetLngLat = {
+ lng: this.selectedRouteCoordinates[0][0],
+ lat: this.selectedRouteCoordinates[0][1],
+ };
- console.log('Bearing: ', result.bearing);
- console.log('Altitude: ', result.altitude);
- }
+ const animationUtil = new AnimationUtility(
+ targetLngLat,
+ this.selectedRouteCoordinates,
+ this.isStreetViewAnimation,
+ this.animationSpeed,
+ this.showTerrain,
+ this._mapRef.current
+ );
+ runInAction(() => {
+ this.setAnimationUtility(animationUtil);
+ })
- runInAction(() => {
- 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({
+ const updateFrameId = (newFrameId: number) => {
+ this.setFrameId(newFrameId);
+ }
+
+ const updateAnimationPhase = (
+ newAnimationPhase: number,
+ ) => {
+ this.setAnimationPhase(newAnimationPhase);
+ };
+
+ if (status !== AnimationStatus.RESUME) {
+
+ const result = await animationUtil.flyInAndRotate({
map: this._mapRef.current!,
- // path: this.path,
- // startBearing: -20,
- // startAltitude: this.isStreetViewAnimation ? 80 : 12000,
- // pitch: this.isStreetViewAnimation ? 80: 50,
- currentAnimationPhase: this.animationPhase,
- updateAnimationPhase,
+ // targetLngLat,
+ // duration 3000
+ // startAltitude: 3000000,
+ // endAltitude: this.isStreetViewAnimation ? 80 : 12000,
+ // startBearing: 0,
+ // endBearing: -20,
+ // startPitch: 40,
+ // endPitch: this.isStreetViewAnimation ? 80 : 50,
updateFrameId,
});
- // get the bounds of the linestring, use fitBounds() to animate to a final view
- const bbox3d = turf.bbox(this.path);
+ console.log("Bearing: ", result.bearing);
+ console.log("Altitude: ", result.altitude);
- const bbox2d: LngLatBoundsLike = [bbox3d[0], bbox3d[1], bbox3d[2], bbox3d[3]];
+ }
- this._mapRef.current!.fitBounds(bbox2d, {
- duration: 3000,
- pitch: 30,
- bearing: 0,
- padding: 120,
- });
-
- setTimeout(() => {
- resolve();
- }, 10000);
- } catch (error: any) {
- console.log(error);
- console.log('animation util: ', animationUtil);
- }
+ runInAction(() => {
+ 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!,
+ // path: this.path,
+ // startBearing: -20,
+ // startAltitude: this.isStreetViewAnimation ? 80 : 12000,
+ // pitch: this.isStreetViewAnimation ? 80: 50,
+ currentAnimationPhase: this.animationPhase,
+ updateAnimationPhase,
+ updateFrameId,
+ });
+
+ // get the bounds of the linestring, use fitBounds() to animate to a final view
+ const bbox3d = turf.bbox(this.path);
+
+ const bbox2d: LngLatBoundsLike = [bbox3d[0], bbox3d[1], bbox3d[2], bbox3d[3]];
+
+ this._mapRef.current!.fitBounds(bbox2d, {
+ duration: 3000,
+ pitch: 30,
+ bearing: 0,
+ padding: 120,
+ });
+
+ setTimeout(() => {
+ 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
- stopAndCloseAnimation = () => {
- if (this.frameId) {
+ stopAnimation = (close: boolean) => {
+ if (this.frameId){
window.cancelAnimationFrame(this.frameId);
- this.frameId = null;
- this.finishedFlyTo = false;
- this.isAnimating = false;
- this.animationPhase = 0;
+ }
+ this.animationPhase = 0;
+ this.frameId = null;
+ this.finishedFlyTo = false;
+ this.isAnimating = false;
+ if (close) {
+ this.animationSpeed = AnimationSpeed.MEDIUM;
+ this.isStreetViewAnimation = false;
this.routeToAnimate = undefined;
- // this.selectedRouteCoordinates = [];
+ this.animationUtility = null;
}
- // reset bearing and pitch to original, zoom out
- };
+ if (this.preAnimationViewState){
+ this.mapboxMapViewState = this.preAnimationViewState;
+ }
+
+
+ }
@action
- exportAnimationToVideo = () => {};
+ exportAnimationToVideo = () => {
+
+ }
getRouteAnimationOptions = (): JSX.Element => {
return (
<>
- <IconButton
+ <IconButton
tooltip={this.isAnimating && this.finishedFlyTo ? 'Pause Animation' : 'Play Animation'}
onPointerDown={() => {
if (this.isAnimating && this.finishedFlyTo) {
@@ -1344,60 +1467,90 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this.playAnimation(AnimationStatus.START); // Play from the beginning
}
}}
- icon={this.isAnimating && this.finishedFlyTo ? <FontAwesomeIcon icon={faPause as IconLookup} /> : <FontAwesomeIcon icon={faPlay as IconLookup} />}
- color="black"
+ icon={this.isAnimating && this.finishedFlyTo ?
+ <FontAwesomeIcon icon={faPause as IconLookup}/>
+ :
+ <FontAwesomeIcon icon={faPlay as IconLookup}/>
+ }
+ color='black'
size={Size.MEDIUM}
/>
- {this.isAnimating && this.finishedFlyTo && (
- <IconButton tooltip="Restart animation" onPointerDown={() => this.playAnimation(AnimationStatus.RESTART)} icon={<FontAwesomeIcon icon={faRotate as IconLookup} />} color="black" size={Size.MEDIUM} />
- )}
- <IconButton tooltip="Stop and close animation" onPointerDown={this.stopAndCloseAnimation} icon={<FontAwesomeIcon icon={faCircleXmark as IconLookup} />} color="black" size={Size.MEDIUM} />
- <IconButton style={{ marginRight: '10px' }} tooltip="Export to video" onPointerDown={this.exportAnimationToVideo} icon={<FontAwesomeIcon icon={faFileExport as IconLookup} />} color="black" size={Size.MEDIUM} />
- {!this.isAnimating && (
- <>
- <div className="animation-suboptions">
- <div>|</div>
- <FormControlLabel label="Street view animation" labelPlacement="start" control={<Checkbox color="success" checked={this.isStreetViewAnimation} onChange={this.toggleIsStreetViewAnimation} />} />
- <div id="last-divider">|</div>
- <IconButton tooltip={this.animationSpeedTooltipText} onPointerDown={this.updateAnimationSpeed} icon={this.animationSpeedIcon} size={Size.MEDIUM} />
- </div>
- </>
- )}
+ {this.isAnimating && this.finishedFlyTo &&
+ <IconButton
+ tooltip='Restart animation'
+ onPointerDown={() => {
+ this.stopAnimation(false);
+ this.playAnimation(AnimationStatus.START)
+ }}
+ icon={<FontAwesomeIcon icon={faRotate as IconLookup}/>}
+ color='black'
+ size={Size.MEDIUM}
+ />
+
+ }
+ <IconButton
+ style={{marginRight: '10px'}}
+ tooltip='Stop and close animation'
+ onPointerDown={() => this.stopAnimation(true)}
+ icon={<FontAwesomeIcon icon={faCircleXmark as IconLookup}/>}
+ color='black'
+ size={Size.MEDIUM}
+ />
+ <>
+ <div className='animation-suboptions'>
+ <div>|</div>
+ <FormControlLabel
+ className='first-person-label'
+ style={{width: '130px'}}
+ label='1st person animation:'
+ labelPlacement='start'
+ control={
+ <Checkbox
+ color='success'
+ checked={this.isStreetViewAnimation}
+ onChange={this.toggleIsStreetViewAnimation}
+ />
+ }
+ />
+ <div id='divider'>|</div>
+ <IconButton
+ tooltip={this.animationSpeedTooltipText}
+ onPointerDown={this.updateAnimationSpeed}
+ icon={this.animationSpeedIcon}
+ size={Size.MEDIUM}
+ />
+ <div id='divider'>|</div>
+ <div style={{width: '230px'}}>Select Line Color: </div>
+ <CirclePicker
+ circleSize={12}
+ circleSpacing={5}
+ width='100%'
+ colors={['#ffff00', '#03a9f4', '#ff0000', '#ff5722', '#000000', '#673ab7']}
+ onChange={(color) => this.setAnimationLineColor(color)}
+ />
+ </div>
+ </>
</>
- );
- };
+ )
+ }
@action
hideRoute = () => {
this.temporaryRouteSource = {
type: 'FeatureCollection',
- features: [],
- };
- };
+ features: []
+ }
+ }
- @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
+ @observable
settingsOpen: boolean = false;
- @observable
- mapStyle: string = 'mapbox://styles/mapbox/streets-v12';
+ @observable
+ mapStyle: string = 'mapbox://styles/mapbox/streets-v12'
@observable
- showTerrain: boolean = false;
+ showTerrain: boolean = true;
@action
toggleSettings = () => {
@@ -1405,51 +1558,103 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this.featuresFromGeocodeResults = [];
this.settingsOpen = !this.settingsOpen;
}
- };
+ }
@action
changeMapStyle = (e: React.ChangeEvent<HTMLSelectElement>) => {
- this.mapStyle = `mapbox://styles/mapbox/${e.target.value}`;
- };
+ this.dataDoc.map_style = `mapbox://styles/mapbox/${e.target.value}`;
+ // this.mapStyle = `mapbox://styles/mapbox/${e.target.value}`
+ }
- @action
- onMapMove = (e: ViewStateChangeEvent) => {
- this.mapboxMapViewState = e.viewState;
- };
+ @action
+ onBearingChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+ const bearing = parseInt(e.target.value);
+ 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
+ }
+ }
+ }
- @action
- toggleShowTerrain = () => {
- this.showTerrain = !this.showTerrain;
- };
+ @action
+ onPitchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+ const pitch = parseInt(e.target.value);
+ 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
+ }
+ }
+ }
- @action
- onBearingChange = (e: React.ChangeEvent<HTMLInputElement>) => {
- const newVal = parseInt(e.target.value);
- if (!isNaN(newVal) && newVal >= 0) {
+ @action
+ onZoomChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+ const zoom = parseInt(e.target.value);
+ 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,
- bearing: parseInt(e.target.value),
- };
+ zoom: fixedZoom
+ }
}
- };
+ }
@action
- onPitchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
- const newVal = parseInt(e.target.value);
- if (!isNaN(newVal) && newVal >= 0) {
+ onStepZoomChange = (increment: boolean) => {
+ if (this._mapRef.current) {
+ let newZoom: number;
+ if (increment) {
+ console.log('inc')
+ newZoom = this.mapboxMapViewState.zoom + 1;
+
+ } else {
+ console.log('dec')
+ newZoom = this.mapboxMapViewState.zoom - 1;
+ }
+ this._mapRef.current.setZoom(newZoom);
+ this.dataDoc.map_zoom = newZoom;
this.mapboxMapViewState = {
...this.mapboxMapViewState,
- pitch: parseInt(e.target.value),
- };
+ 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;
@@ -1457,7 +1662,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
render() {
// bcz: no idea what's going on here, but bings maps have some kind of bug
// such that we need to delay rendering a second map on startup until the first map is rendered.
- this.Document[DocCss];
+ this.rootDoc[DocCss];
if (MapBox._rerenderDelay) {
// prettier-ignore
this._rerenderTimeout = this._rerenderTimeout ??
@@ -1466,12 +1671,14 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
MapBox._rerenderDelay = 0;
}
this._rerenderTimeout = undefined;
- this.Document[DocCss] = this.Document[DocCss] + 1;
+ this.rootDoc[DocCss] = this.rootDoc[DocCss] + 1;
}), MapBox._rerenderDelay);
return null;
}
const scale = this.props.NativeDimScaling?.() || 1;
+
+ const renderAnnotations = (childFilters?: () => string[]) => null;
return (
<div className="mapBox" ref={this._ref}>
<div
@@ -1480,164 +1687,235 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
onPointerDown={async e => {
e.button === 0 && !e.ctrlKey && e.stopPropagation();
}}
- style={{ transformOrigin: 'top left', transform: `scale(${scale})`, width: `${100 / scale}%`, height: `${100 / scale}%`, pointerEvents: this.pointerEvents() }}>
- {!this.routeToAnimate && (
+ style={{ transformOrigin: "top left", transform: `scale(${scale})`, width: `${100 / scale}%`, height: `${100 / scale}%`, pointerEvents: this.pointerEvents() }}>
+ <div style={{ mixBlendMode: 'multiply' }}>{renderAnnotations(this.transparentFilter)}</div>
+ {renderAnnotations(this.opaqueFilter)}
+ {SnappingManager.GetIsDragging() ? null : renderAnnotations()}
+ {!this.routeToAnimate &&
<div className="mapBox-searchbar">
- <TextField fullWidth placeholder="Enter a location" onChange={(e: any) => this.handleSearchChange(e.target.value)} />
- <IconButton icon={<FontAwesomeIcon icon={faGear as IconLookup} size="1x" />} type={Type.TERT} onClick={e => this.toggleSettings()} />
- </div>
- )}
- {this.settingsOpen && !this.routeToAnimate && (
- <div className="mapbox-settings-panel" style={{ right: `${0 + this.sidebarWidth()}px` }}>
- <div className="mapbox-style-select">
- <div>Map Style:</div>
+ <TextField
+ fullWidth
+ placeholder='Enter a location'
+ onChange={(e) => this.handleSearchChange(e.target.value)}
+ />
+ <IconButton
+ icon={<FontAwesomeIcon icon={faGear as IconLookup} size='1x'/>}
+ type={Type.TERT}
+ onClick={(e) => this.toggleSettings()}
+
+ />
+ </div>
+ }
+ {this.settingsOpen && !this.routeToAnimate &&
+ <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>
+ <option value='streets-v11'>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 className='mapbox-bearing-selection'>
<div>Bearing: </div>
- <input value={this.mapboxMapViewState.bearing} min={0} type="number" onChange={this.onBearingChange} />
+ <input
+ value={NumCast(this.mapboxMapViewState.bearing).toFixed(2)}
+ type='number'
+ onChange={this.onBearingChange}/>
</div>
- <div className="mapbox-pitch-selection">
+ <div className='mapbox-pitch-selection'>
<div>Pitch: </div>
- <input value={this.mapboxMapViewState.pitch} min={0} type="number" onChange={this.onPitchChange} />
+ <input
+ value={NumCast(this.mapboxMapViewState.pitch).toFixed(2)}
+ type='number'
+ onChange={this.onPitchChange}/>
+ </div>
+ <div className='mapbox-pitch-selection'>
+ <div>Zoom: </div>
+ <input
+ value={NumCast(this.mapboxMapViewState.zoom).toFixed(2)}
+ type='number'
+ onChange={this.onZoomChange}/>
</div>
- <div className="mapbox-terrain-selection">
+ <div className='mapbox-terrain-selection'>
<div>Show terrain: </div>
- <input type="checkbox" checked={this.showTerrain} onChange={this.toggleShowTerrain} />
+ <input
+ type='checkbox'
+ checked={this.showTerrain}
+ onChange={this.toggleShowTerrain}
+ />
</div>
</div>
- )}
- {this.routeToAnimate && (
- <div className="animation-panel">
- <div id="route-to-animate-title">{StrCast(this.routeToAnimate.title)}</div>
- <div className="route-animation-options">{this.getRouteAnimationOptions()}</div>
+ }
+ {this.routeToAnimate &&
+ <div className='animation-panel'>
+ <div id='route-to-animate-title'>
+ {StrCast(this.routeToAnimate.title)}
+ </div>
+ <div className='route-animation-options'>
+ {this.getRouteAnimationOptions()}
+ </div>
</div>
- )}
+ }
{this.featuresFromGeocodeResults.length > 0 && (
- <div className="mapbox-geocoding-search-results">
+ <div className='mapbox-geocoding-search-results'>
<React.Fragment>
<h4>Choose a location for your pin: </h4>
{this.featuresFromGeocodeResults
.filter(feature => feature.place_name)
.map((feature, idx) => (
- <div
- key={idx}
- className="search-result-container"
- onClick={() => {
- this.handleSearchChange('');
- this.addMarkerForFeature(feature);
- }}>
- <div className="search-result-place-name">{feature.place_name}</div>
+ <div
+ key={idx}
+ className='search-result-container'
+ onClick={() => {
+ this.handleSearchChange("");
+ this.addMarkerForFeature(feature);
+ }}
+ >
+ <div className='search-result-place-name'>
+ {feature.place_name}
</div>
- ))}
+ </div>
+ ))}
</React.Fragment>
- </div>
+
+ </div>
)}
+ {/* <div className='zoom-box'>
+ <IconButton // increment
+ style={{borderBottom: '1px', borderBottomColor: 'white'}}
+ onPointerDown={() => this.onStepZoomChange(true)}
+ icon={<FontAwesomeIcon icon={faPlus as IconLookup} color='black'/>}
+ size={Size.SMALL}
+ color={SettingsManager.userColor}
+ />
+ <IconButton // decrement
+ onPointerDown={() => this.onStepZoomChange(false)}
+ icon={<FontAwesomeIcon icon={faMinus as IconLookup} color='black'/>}
+ size={Size.SMALL}
+ color={SettingsManager.userColor}
+ />
+ </div> */}
<MapProvider>
<MapboxMap
ref={this._mapRef}
mapboxAccessToken={MAPBOX_ACCESS_TOKEN}
id="mapbox-map"
- mapStyle={this.mapStyle}
- style={{ height: '100%', width: '100%' }}
+ mapStyle={this.dataDoc.map_style ? StrCast(this.dataDoc.map_style) : 'mapbox://styles/mapbox/streets-v11'}
+ style={{height: NumCast(this.layoutDoc._height), width: NumCast(this.layoutDoc._width)}}
initialViewState={this.isAnimating ? undefined : this.mapboxMapViewState}
- // {...this.mapboxMapViewState}
onMove={this.onMapMove}
onClick={this.handleMapClick}
onDblClick={this.handleMapDblClick}
- 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" source="temporary-route" layout={{ 'line-join': 'round', 'line-cap': 'round' }} paint={{ 'line-color': '#36454F', 'line-width': 4, 'line-dasharray': [1, 1] }} />
- {!this.isAnimating && this.animationPhase == 0 && <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.routeToAnimate && (this.isAnimating || this.animationPhase > 0) && (
+ 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'
+ source='temporary-route'
+ layout={{"line-join": "round", "line-cap": "round"}}
+ paint={{"line-color": "#36454F", "line-width": 4, "line-dasharray": [1,1]}}
+ />
+ {!this.isAnimating && this.animationPhase == 0 &&
+ <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.routeToAnimate && (this.isAnimating || this.animationPhase > 0) &&
<>
- {!this.isStreetViewAnimation && (
+ {!this.isStreetViewAnimation &&
<>
- <Source id="animated-route" type="geojson" data={this.updatedRouteCoordinates} />
- <Layer
- id="dynamic-animation-line"
- type="line"
- source="animated-route"
- paint={{
- 'line-color': 'yellow',
- 'line-width': 4,
- }}
+ <Source id='animated-route' type='geojson' data={this.updatedRouteCoordinates}/>
+ <Layer
+ id='dynamic-animation-line'
+ type='line'
+ source='animated-route'
+ paint={{
+ 'line-color': this.animationLineColor,
+ 'line-width': 5,
+ }}
/>
</>
- )}
- <Source id="start-pin-base" type="geojson" data={AnimationUtility.createGeoJSONCircle(this.selectedRouteCoordinates[0], 0.04)} />
- <Source id="start-pin-top" type="geojson" data={AnimationUtility.createGeoJSONCircle(this.selectedRouteCoordinates[0], 0.25)} />
- <Source id="end-pin-base" type="geojson" data={AnimationUtility.createGeoJSONCircle(this.selectedRouteCoordinates.slice(-1)[0], 0.04)} />
- <Source id="end-pin-top" type="geojson" data={AnimationUtility.createGeoJSONCircle(this.selectedRouteCoordinates.slice(-1)[0], 0.25)} />
- <Layer
- id="start-fill-pin-base"
- type="fill-extrusion"
- source="start-pin-base"
+ }
+ <Source id='start-pin-base' type='geojson' data={AnimationUtility.createGeoJSONCircle(this.selectedRouteCoordinates[0], 0.04)}/>
+ <Source id='start-pin-top' type='geojson' data={AnimationUtility.createGeoJSONCircle(this.selectedRouteCoordinates[0], 0.25)}/>
+ <Source id='end-pin-base' type='geojson' data={AnimationUtility.createGeoJSONCircle(this.selectedRouteCoordinates.slice(-1)[0], 0.04)}/>
+ <Source id='end-pin-top' type='geojson' data={AnimationUtility.createGeoJSONCircle(this.selectedRouteCoordinates.slice(-1)[0], 0.25)}/>
+ <Layer id='start-fill-pin-base' type='fill-extrusion' source='start-pin-base'
paint={{
'fill-extrusion-color': '#0bfc03',
- 'fill-extrusion-height': 1000,
+ 'fill-extrusion-height': 1000
}}
/>
- <Layer
- id="start-fill-pin-top"
- type="fill-extrusion"
- source="start-pin-top"
+ <Layer id='start-fill-pin-top' type='fill-extrusion' source='start-pin-top'
paint={{
'fill-extrusion-color': '#0bfc03',
'fill-extrusion-base': 1000,
- 'fill-extrusion-height': 1200,
+ 'fill-extrusion-height': 1200
}}
/>
- <Layer
- id="end-fill-pin-base"
- type="fill-extrusion"
- source="end-pin-base"
+ <Layer id='end-fill-pin-base' type='fill-extrusion' source='end-pin-base'
paint={{
'fill-extrusion-color': '#eb1c1c',
- 'fill-extrusion-height': 1000,
+ 'fill-extrusion-height': 1000
}}
/>
- <Layer
- id="end-fill-pin-top"
- type="fill-extrusion"
- source="end-pin-top"
+ <Layer id='end-fill-pin-top' type='fill-extrusion' source='end-pin-top'
paint={{
'fill-extrusion-color': '#eb1c1c',
'fill-extrusion-base': 1000,
- 'fill-extrusion-height': 1200,
+ 'fill-extrusion-height': 1200
}}
/>
+
</>
- )}
+ }
+
<>
- {!this.isAnimating &&
- this.animationPhase == 0 &&
- this.allPushpins
- // .filter(anno => !anno.layout_unrendered)
- .map((pushpin, idx) => (
- <Marker key={idx} longitude={NumCast(pushpin.longitude)} latitude={NumCast(pushpin.latitude)} anchor="bottom" onClick={(e: MarkerEvent<mapboxgl.Marker, MouseEvent>) => this.handleMarkerClick(e, pushpin)}>
- {this.getMarkerIcon(pushpin)}
- </Marker>
- ))}
+ {!this.isAnimating && this.animationPhase == 0 && this.allPushpins
+ // .filter(anno => !anno.layout_unrendered)
+ .map((pushpin, idx) => (
+ <Marker
+ key={idx}
+ longitude={NumCast(pushpin.longitude)}
+ latitude={NumCast(pushpin.latitude)}
+ anchor='bottom'
+ onClick={(e: MarkerEvent<mapboxgl.Marker, MouseEvent>) => this.handleMarkerClick(e, pushpin)}
+ >
+ {this.getMarkerIcon(pushpin)}
+ </Marker>
+ ))}
</>
-
+
{/* {this.mapMarkers.length > 0 && this.mapMarkers.map((marker, idx) => (
<Marker key={idx} longitude={marker.longitude} latitude={marker.latitude}/>
))} */}
+
</MapboxMap>
</MapProvider>
@@ -1657,10 +1935,10 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
.map((pushpin, i) => (
<DocumentView
key={i}
- {...this._props}
- renderDepth={this._props.renderDepth + 1}
+ {...this.props}
+ renderDepth={this.props.renderDepth + 1}
Document={pushpin}
- TemplateDataDocument={undefined}
+ DataDoc={undefined}
PanelWidth={returnOne}
PanelHeight={returnOne}
NativeWidth={returnOne}
@@ -1682,7 +1960,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
</div> */}
{/* <MapBoxInfoWindow
key={Docs.Create.MapMarkerDocument(NumCast(40), NumCast(40), false, [], {})[Id]}
- {...OmitKeys(this._props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
+ {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
place={Docs.Create.MapMarkerDocument(NumCast(40), NumCast(40), false, [], {})}
markerMap={this.markerMap}
PanelWidth={this.infoWidth}
@@ -1696,9 +1974,9 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
<div className="mapBox-sidebar" style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
<SidebarAnnos
ref={this._sidebarRef}
- {...this._props}
+ {...this.props}
fieldKey={this.fieldKey}
- Document={this.Document}
+ rootDoc={this.rootDoc}
layoutDoc={this.layoutDoc}
dataDoc={this.dataDoc}
usePanelWidth={true}
@@ -1717,8 +1995,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}
}
-{
- /* <Autocomplete
+{/* <Autocomplete
fullWidth
id="map-location-searcher"
freeSolo
@@ -1737,10 +2014,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
placeholder='Enter a location'
/>
)}
- /> */
-}
-{
- /* <EditableText
+ /> */}
+ {/* <EditableText
// editing
setVal={(newText: string | number) => typeof newText === 'string' && this.handleSearchChange(newText)}
// onEnter={e => this.bingSearch()}
@@ -1749,10 +2024,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
// placeholder={this.bingSearchBarContents || 'Enter a location'}
placeholder='Enter a location'
textAlign="center"
- /> */
-}
-{
- /* <IconButton
+ /> */}
+ {/* <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
@@ -1765,5 +2038,4 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
/>
<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> */}