aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/MapBox
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/MapBox')
-rw-r--r--src/client/views/nodes/MapBox/MapBox.tsx794
-rw-r--r--src/client/views/nodes/MapBox/MapPushpinBox.tsx4
2 files changed, 196 insertions, 602 deletions
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index 927e6fad4..b73898f59 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -6,7 +6,7 @@ import { IconButton, Size, Type } from 'browndash-components';
import * as d3 from 'd3';
import { Feature, FeatureCollection, GeoJsonProperties, Geometry, LineString, Position } from 'geojson';
import mapboxgl, { LngLat, LngLatBoundsLike, MapLayerMouseEvent } from 'mapbox-gl';
-import { IReactionDisposer, ObservableMap, action, autorun, computed, makeObservable, observable, reaction, runInAction } from 'mobx';
+import { IReactionDisposer, ObservableMap, action, autorun, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { CirclePicker, ColorResult } from 'react-color';
@@ -14,7 +14,6 @@ import { Layer, MapProvider, MapRef, Map as MapboxMap, Marker, Source, ViewState
import { MarkerEvent } from 'react-map-gl/dist/esm/types';
import { Utils, emptyFunction, setupMoveUpEvents } from '../../../../Utils';
import { Doc, DocListCast, Field, LinkedTo, Opt } from '../../../../fields/Doc';
-import { DocCss, Highlight } from '../../../../fields/DocSymbols';
import { DocCast, NumCast, StrCast } from '../../../../fields/Types';
import { DocumentType } from '../../../documents/DocumentTypes';
import { DocUtils, Docs } from '../../../documents/Documents';
@@ -28,7 +27,7 @@ import { SidebarAnnos } from '../../SidebarAnnos';
import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm';
import { Colors } from '../../global/globalEnums';
import { DocumentView } from '../DocumentView';
-import { FocusViewOptions, FieldView, FieldViewProps } from '../FieldView';
+import { FieldView, FieldViewProps, FocusViewOptions } from '../FieldView';
import { FormattedTextBox } from '../formattedText/FormattedTextBox';
import { PinProps, PresBox } from '../trails';
import { fastSpeedIcon, mediumSpeedIcon, slowSpeedIcon } from './AnimationSpeedIcons';
@@ -53,7 +52,6 @@ import { MarkerIcons } from './MarkerIcons';
* A map marker is considered a document that contains a collection with stacking view of documents, it has a lat, lng location, which is passed to Maps API's custom marker (red pin) to be rendered on the google maps
*/
-const bingApiKey = process.env.BING_MAPS; // if you're running local, get a Bing Maps api key here: https://www.bingmapsportal.com/ and then add it to the .env file in the Dash-Web root directory as: _CLIENT_BING_MAPS=<your apikey>
const MAPBOX_ACCESS_TOKEN = 'pk.eyJ1IjoiemF1bHRhdmFuZ2FyIiwiYSI6ImNscHgwNDd1MDA3MXIydm92ODdianp6cGYifQ.WFAqbhwxtMHOWSPtu0l2uQ';
const MAPBOX_FORWARD_GEOCODE_BASE_URL = 'https://api.mapbox.com/geocoding/v5/mapbox.places/';
@@ -66,72 +64,69 @@ type PopupInfo = {
description: string;
};
-// export type GeocoderControlProps = Omit<GeocoderOptions, 'accessToken' | 'mapboxgl' | 'marker'> & {
-// mapboxAccessToken: string;
-// marker?: Omit<MarkerProps, 'longitude' | 'latitude'>;
-// position: ControlPosition;
-
-// onResult: (...args: any[]) => void;
-// };
-
-type MapMarker = {
- longitude: number;
- latitude: number;
-};
-
-/**
- * Consider integrating later: allows for drawing, circling, making shapes on map
- */
-// const drawingManager = new window.google.maps.drawing.DrawingManager({
-// drawingControl: true,
-// drawingControlOptions: {
-// position: google.maps.ControlPosition.TOP_RIGHT,
-// drawingModes: [
-// google.maps.drawing.OverlayType.MARKER,
-// // currently we are not supporting the following drawing mode on map, a thought for future development
-// google.maps.drawing.OverlayType.CIRCLE,
-// google.maps.drawing.OverlayType.POLYLINE,
-// ],
-// },
-// });
-
@observer
export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implements ViewBoxInterface {
public static LayoutString(fieldKey: string) {
return FieldView.LayoutString(MapBox, fieldKey);
}
- private _dragRef = React.createRef<HTMLDivElement>();
+ private _unmounting = false;
private _sidebarRef = React.createRef<SidebarAnnos>();
private _ref: React.RefObject<HTMLDivElement> = React.createRef();
private _mapRef: React.RefObject<MapRef> = React.createRef();
private _disposers: { [key: string]: IReactionDisposer } = {};
- private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void);
constructor(props: FieldViewProps) {
super(props);
makeObservable(this);
}
- @observable private _savedAnnotations = new ObservableMap<number, HTMLDivElement[]>();
- @computed get allSidebarDocs() {
- return DocListCast(this.dataDoc[this.SidebarKey]);
- }
+ @observable _featuresFromGeocodeResults: any[] = [];
+ @observable _savedAnnotations = new ObservableMap<number, HTMLDivElement[]>();
+ @observable _selectedPinOrRoute: Doc | undefined = undefined; // The pin that is selected
+ @observable _mapReady = false;
+ @observable _isAnimating: boolean = false;
+ @observable _routeToAnimate: Doc | undefined = undefined;
+ @observable _animationPhase: number = 0;
+ @observable _finishedFlyTo: boolean = false;
+ @observable _frameId: number | null = null;
+ @observable _animationUtility: AnimationUtility | null = null;
+ @observable _settingsOpen: boolean = false;
+ @observable _mapStyle: string = 'mapbox://styles/mapbox/standard';
+ @observable _showTerrain: boolean = true;
+ @observable _currentPopup: PopupInfo | undefined = undefined;
+ @observable _isStreetViewAnimation: boolean = false;
+ @observable _animationSpeed: AnimationSpeed = AnimationSpeed.MEDIUM;
+ @observable _animationLineColor: string = '#ffff00';
+ @observable _temporaryRouteSource: FeatureCollection = { type: 'FeatureCollection', features: [] };
+ @observable _dynamicRouteFeature: Feature<Geometry, GeoJsonProperties> = {
+ type: 'Feature',
+ properties: {},
+ geometry: { type: 'LineString', coordinates: [] },
+ };
+
+ @observable path: turf.helpers.Feature<turf.helpers.LineString, turf.helpers.Properties> = {
+ type: 'Feature',
+ geometry: { type: 'LineString', coordinates: [] },
+ properties: {},
+ };
+
// this list contains pushpins and configs
- @computed get allAnnotations() {
- return DocListCast(this.dataDoc[this.annotationKey]);
- }
- @computed get allPushpins() {
- return this.allAnnotations.filter(anno => anno.type === DocumentType.PUSHPIN);
- }
- @computed get allRoutes() {
- return this.allAnnotations.filter(anno => anno.type === DocumentType.MAPROUTE);
+ @computed get allAnnotations() { return DocListCast(this.dataDoc[this.annotationKey]); } //prettier-ignore
+ @computed get allSidebarDocs() { return DocListCast(this.dataDoc[this.SidebarKey]); } //prettier-ignore
+ @computed get allPushpins() { return this.allAnnotations.filter(anno => anno.type === DocumentType.PUSHPIN); } //prettier-ignore
+ @computed get allRoutes() { return this.allAnnotations.filter(anno => anno.type === DocumentType.MAPROUTE); } //prettier-ignore
+ @computed get SidebarShown() { return this.layoutDoc._layout_showSidebar ? true : false; } //prettier-ignore
+ @computed get sidebarWidthPercent() { return StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%'); } //prettier-ignore
+ @computed get SidebarKey() { return this.fieldKey + '_sidebar'; } //prettier-ignore
+ @computed get sidebarColor() {
+ return StrCast(this.layoutDoc.sidebar_color, StrCast(this.layoutDoc[this._props.fieldKey + '_backgroundColor'], '#e4e4e4'));
}
@computed get updatedRouteCoordinates(): Feature<Geometry, GeoJsonProperties> {
- if (this.routeToAnimate?.routeCoordinates) {
- const originalCoordinates: Position[] = JSON.parse(StrCast(this.routeToAnimate.routeCoordinates));
+ if (this._routeToAnimate?.routeCoordinates) {
+ 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 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>;
@@ -147,7 +142,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
feature = {
type: 'Feature',
properties: {
- routeTitle: StrCast(this.routeToAnimate.title),
+ routeTitle: StrCast(this._routeToAnimate.title),
},
geometry: geometry,
};
@@ -158,9 +153,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
const fraction = index - startIndex;
const interpolator = d3.interpolateArray(startCoord, endCoord);
-
const interpolatedCoord = interpolator(fraction);
-
const coordinates = originalCoordinates.slice(0, startIndex + 1).concat([interpolatedCoord]);
geometry = {
@@ -170,14 +163,14 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
feature = {
type: 'Feature',
properties: {
- routeTitle: StrCast(this.routeToAnimate.title),
+ routeTitle: StrCast(this._routeToAnimate.title),
},
geometry: geometry,
};
}
autorun(() => {
- const animationUtil = this.animationUtility;
+ const animationUtil = this._animationUtility;
const concattedCoordinates = geometry.coordinates.concat(originalCoordinates.slice(endIndex));
const newFeature: Feature<LineString, turf.Properties> = {
type: 'Feature',
@@ -204,11 +197,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
};
}
@computed get selectedRouteCoordinates(): Position[] {
- let coordinates: Position[] = [];
- if (this.routeToAnimate?.routeCoordinates) {
- coordinates = JSON.parse(StrCast(this.routeToAnimate.routeCoordinates));
- }
- return coordinates;
+ return !this._routeToAnimate?.routeCoordinates ? [] : JSON.parse(StrCast(this._routeToAnimate.routeCoordinates));
}
@computed get allRoutesGeoJson(): FeatureCollection {
@@ -233,29 +222,14 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
};
}
- @computed get SidebarShown() {
- return this.layoutDoc._layout_showSidebar ? true : false;
- }
- @computed get sidebarWidthPercent() {
- return StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%');
- }
- @computed get sidebarColor() {
- return StrCast(this.layoutDoc.sidebar_color, StrCast(this.layoutDoc[this._props.fieldKey + '_backgroundColor'], '#e4e4e4'));
- }
- @computed get SidebarKey() {
- return this.fieldKey + '_sidebar';
- }
-
componentDidMount() {
this._unmounting = false;
this._props.setContentViewBox?.(this);
}
- _unmounting = false;
- componentWillUnmount(): void {
+ componentWillUnmount() {
this._unmounting = true;
this.deselectPinOrRoute();
- this._rerenderTimeout && clearTimeout(this._rerenderTimeout);
Object.keys(this._disposers).forEach(key => this._disposers[key]?.());
}
@@ -269,7 +243,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
if (!this.layoutDoc._layout_showSidebar) this.toggleSidebar();
const docs = doc instanceof Doc ? [doc] : doc;
docs.forEach(doc => {
- let existingPin = this.allPushpins.find(pin => pin.latitude === doc.latitude && pin.longitude === doc.longitude) ?? this.selectedPinOrRoute;
+ let existingPin = this.allPushpins.find(pin => pin.latitude === doc.latitude && pin.longitude === doc.longitude) ?? this._selectedPinOrRoute;
if (doc.latitude !== undefined && doc.longitude !== undefined && !existingPin) {
existingPin = this.createPushpin(NumCast(doc.latitude), NumCast(doc.longitude), StrCast(doc.map));
}
@@ -370,10 +344,10 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
const sourceAnchorCreator = action(() => {
const note = this.getAnchor(true);
- if (note && this.selectedPinOrRoute) {
- note.latitude = this.selectedPinOrRoute.latitude;
- note.longitude = this.selectedPinOrRoute.longitude;
- note.map = this.selectedPinOrRoute.map;
+ if (note && this._selectedPinOrRoute) {
+ note.latitude = this._selectedPinOrRoute.latitude;
+ note.longitude = this._selectedPinOrRoute.longitude;
+ note.map = this._selectedPinOrRoute.map;
}
return note as Doc;
});
@@ -399,10 +373,10 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
const createFunc = undoable(
action(() => {
const note = this._sidebarRef.current?.anchorMenuClick(this.getAnchor(true), ['latitude', 'longitude', LinkedTo]);
- if (note && this.selectedPinOrRoute) {
- note.latitude = this.selectedPinOrRoute.latitude;
- note.longitude = this.selectedPinOrRoute.longitude;
- note.map = this.selectedPinOrRoute.map;
+ if (note && this._selectedPinOrRoute) {
+ note.latitude = this._selectedPinOrRoute.latitude;
+ note.longitude = this._selectedPinOrRoute.longitude;
+ note.map = this._selectedPinOrRoute.map;
}
}),
'create note annotation'
@@ -423,12 +397,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
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');
-
panelWidth = () => this._props.PanelWidth() / (this._props.NativeDimScaling?.() || 1) - this.sidebarWidth();
panelHeight = () => this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1);
scrollXf = () => this.ScreenToLocalBoxXf().translate(0, NumCast(this.layoutDoc._layout_scrollTop));
@@ -439,52 +408,9 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick;
savedAnnotations = () => this._savedAnnotations;
- _bingSearchManager: any;
- _bingMap: any;
- get MicrosoftMaps() {
- return (window as any).Microsoft.Maps;
- }
- // uses Bing Search to retrieve lat/lng for a location. eg.,
- // const results = this.geocodeQuery(map.map, 'Philadelphia, PA');
- // to move the map to that location:
- // const location = await this.geocodeQuery(this._bingMap, 'Philadelphia, PA');
- // this._bingMap.current.setView({
- // mapTypeId: this.MicrosoftMaps.MapTypeId.aerial,
- // center: new this.MicrosoftMaps.Location(loc.latitude, loc.longitude),
- // });
- //
- bingGeocode = (map: any, query: string) => {
- return new Promise<{ latitude: number; longitude: number }>((res, reject) => {
- //If search manager is not defined, load the search module.
- if (!this._bingSearchManager) {
- //Create an instance of the search manager and call the geocodeQuery function again.
- this.MicrosoftMaps.loadModule('Microsoft.Maps.Search', () => {
- this._bingSearchManager = new this.MicrosoftMaps.Search.SearchManager(map.current);
- res(this.bingGeocode(map, query));
- });
- } else {
- this._bingSearchManager.geocode({
- where: query,
- callback: action((r: any) => res(r.results[0].location)),
- errorCallback: (e: any) => reject(),
- });
- }
- });
- };
-
- @observable
- bingSearchBarContents: any = this.Document.map; // For Bing Maps: The contents of the Bing search bar (string)
-
- geoDataRequestOptions = {
- entityType: 'PopulatedPlace',
- };
-
- // The pin that is selected
- @observable selectedPinOrRoute: Doc | undefined = undefined;
-
@action
deselectPinOrRoute = () => {
- if (this.selectedPinOrRoute) {
+ if (this._selectedPinOrRoute) {
// // Removes filter
// Doc.setDocFilter(this.Document, 'latitude', this.selectedPin.latitude, 'remove');
// Doc.setDocFilter(this.Document, 'longitude', this.selectedPin.longitude, 'remove');
@@ -511,79 +437,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
}
return new Promise<Opt<DocumentView>>(res => DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv)));
};
- /*
- * Pushpin onclick
- */
- @action
- pushpinClicked = (pinDoc: Doc) => {
- this.deselectPinOrRoute();
- 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');
-
- this.recolorPin(this.selectedPinOrRoute, 'green');
-
- MapAnchorMenu.Instance.Delete = this.deleteSelectedPinOrRoute;
- MapAnchorMenu.Instance.Center = this.centerOnSelectedPin;
- MapAnchorMenu.Instance.OnClick = this.createNoteAnnotation;
- 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.ScreenToLocalBoxXf().inverse().transformPoint(x, y);
- MapAnchorMenu.Instance.jumpTo(cpt[0], cpt[1], true);
-
- document.addEventListener('pointerdown', this.tryHideMapAnchorMenu, true);
- };
-
- /**
- * Map OnClick
- */
- @action
- mapOnClick = (e: { location: { latitude: any; longitude: any } }) => {
- this._props.select(false);
- this.deselectPinOrRoute();
- };
- /*
- * Updates values of layout doc to match the current map
- */
- @action
- mapRecentered = () => {
- if (
- Math.abs(NumCast(this.dataDoc.latitude) - this._bingMap.current.getCenter().latitude) > 1e-7 || //
- Math.abs(NumCast(this.dataDoc.longitude) - this._bingMap.current.getCenter().longitude) > 1e-7
- ) {
- this.dataDoc.latitude = this._bingMap.current.getCenter().latitude;
- this.dataDoc.longitude = this._bingMap.current.getCenter().longitude;
- this.dataDoc.map = '';
- this.bingSearchBarContents = '';
- }
- this.dataDoc.map_zoom = this._bingMap.current.getZoom();
- };
- /*
- * Updates maptype
- */
- @action
- updateMapType = () => (this.dataDoc.map_type = this._bingMap.current.getMapTypeId());
-
- /*
- * For Bing Maps
- * Called by search button's onClick
- * Finds the geocode of the searched contents and sets location to that location
- **/
- @action
- bingSearch = () => {
- return this.bingGeocode(this._bingMap, this.bingSearchBarContents).then(location => {
- this.dataDoc.latitude = location.latitude;
- this.dataDoc.longitude = location.longitude;
- this.dataDoc.map_zoom = this._bingMap.current.getZoom();
- this.dataDoc.map = this.bingSearchBarContents;
- });
- };
/*
* Returns doc w/ relevant info
@@ -592,14 +445,14 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
/// 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') as any,
- config_latitude: NumCast((existingPin ?? this.selectedPinOrRoute)?.latitude ?? this.dataDoc.latitude),
- config_longitude: NumCast((existingPin ?? this.selectedPinOrRoute)?.longitude ?? this.dataDoc.longitude),
+ text: (StrCast(this._selectedPinOrRoute?.map) || StrCast(this.Document.map) || 'map location') as any,
+ 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: StrCast((existingPin ?? this.selectedPinOrRoute)?.map) || StrCast(this.dataDoc.map),
+ config_map: StrCast((existingPin ?? this._selectedPinOrRoute)?.map) || StrCast(this.dataDoc.map),
layout_unrendered: true,
- mapPin: existingPin ?? this.selectedPinOrRoute,
+ mapPin: existingPin ?? this._selectedPinOrRoute,
annotationOn: this.Document,
});
if (anchor) {
@@ -613,25 +466,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
map_docToPinMap = new Map<Doc, any>();
map_pinHighlighted = new Map<Doc, boolean>();
- /*
- * Input: pin doc
- * Adds MicrosoftMaps Pushpin to the map (render)
- */
- @action
- addPushpin = (pin: Doc) => {
- const pushPin = pin.infoWindowOpen
- ? new this.MicrosoftMaps.Pushpin(new this.MicrosoftMaps.Location(pin.latitude, pin.longitude), {})
- : new this.MicrosoftMaps.Pushpin(
- new this.MicrosoftMaps.Location(pin.latitude, pin.longitude)
- // {icon: 'http://icons.iconarchive.com/icons/icons-land/vista-map-markers/24/Map-Marker-Marker-Outside-Chartreuse-icon.png'}
- );
-
- this._bingMap.current.entities.push(pushPin);
-
- this.MicrosoftMaps.Events.addHandler(pushPin, 'click', (e: any) => this.pushpinClicked(pin));
- // this.MicrosoftMaps.Events.addHandler(pushPin, 'dblclick', (e: any) => this.pushpinDblClicked(pushPin, pin));
- this.map_docToPinMap.set(pin, pushPin);
- };
/*
* Input: pin doc
@@ -640,27 +474,16 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
@action
removePushpinOrRoute = (pinOrRouteDoc: Doc) => this.removeMapDocument(pinOrRouteDoc, this.annotationKey);
- /*
- * Removes pushpin from map render
- */
- deletePushpin = (pinDoc: Doc) => {
- if (!this._unmounting) {
- this._bingMap.current.entities.remove(this.map_docToPinMap.get(pinDoc));
- }
- this.map_docToPinMap.delete(pinDoc);
- this.selectedPinOrRoute = undefined;
- };
-
@action
deleteSelectedPinOrRoute = undoable(() => {
console.log('deleting');
- if (this.selectedPinOrRoute) {
+ 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.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);
+ this.removePushpinOrRoute(this._selectedPinOrRoute);
}
MapAnchorMenu.Instance.fadeOut(true);
document.removeEventListener('pointerdown', this.tryHideMapAnchorMenu, true);
@@ -677,7 +500,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
e.preventDefault();
MapAnchorMenu.Instance.fadeOut(true);
runInAction(() => {
- this.temporaryRouteSource = {
+ this._temporaryRouteSource = {
type: 'FeatureCollection',
features: [],
};
@@ -688,9 +511,9 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
@action
centerOnSelectedPin = () => {
- if (this.selectedPinOrRoute) {
+ 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) {
@@ -703,33 +526,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
document.removeEventListener('pointerdown', this.tryHideMapAnchorMenu);
};
- /**
- * View options for bing maps
- */
- bingViewOptions = {
- // center: { latitude: this.dataDoc.latitude ?? defaultCenter.lat, longitude: this.dataDoc.longitude ?? defaultCenter.lng },
- zoom: this.dataDoc.latitude ?? 10,
- mapTypeId: 'grayscale',
- };
-
- /**
- * Map options
- */
- bingMapOptions = {
- navigationBarMode: 'square',
- backgroundColor: '#f1f3f4',
- enableInertia: true,
- supportedMapTypes: ['grayscale', 'canvasLight'],
- disableMapTypeSelectorMouseOver: true,
- // showScalebar:true
- // disableRoadView:true,
- // disableBirdseye:true
- streetsideOptions: {
- showProblemReporting: false,
- showCurrentAddress: false,
- },
- };
-
recolorPin = (pin: Doc, color?: string) => {
// this._bingMap.current.entities.remove(this.map_docToPinMap.get(pin));
// this.map_docToPinMap.delete(pin);
@@ -739,109 +535,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
// this.map_docToPinMap.set(pin, newpin);
};
- /*
- * Called when BingMap is first rendered
- * Initializes starting values
- */
- @observable _mapReady = false;
- @action
- bingMapReady = (map: any) => {
- this._mapReady = true;
- this._bingMap = map.map;
- if (!this._bingMap.current) {
- alert('NO Map!?');
- }
- this.MicrosoftMaps.Events.addHandler(this._bingMap.current, 'click', this.mapOnClick);
- this.MicrosoftMaps.Events.addHandler(this._bingMap.current, 'viewchangeend', undoable(this.mapRecentered, 'Map Layout Change'));
- this.MicrosoftMaps.Events.addHandler(this._bingMap.current, 'maptypechanged', undoable(this.updateMapType, 'Map ViewType Change'));
-
- this._disposers.mapLocation = reaction(
- () => this.Document.map,
- mapLoc => (this.bingSearchBarContents = mapLoc),
- { fireImmediately: true }
- );
- this._disposers.highlight = reaction(
- () => this.allAnnotations.map(doc => doc[Highlight]),
- () => {
- const allConfigPins = this.allAnnotations.map(doc => ({ doc, pushpin: DocCast(doc.mapPin) })).filter(pair => pair.pushpin);
- allConfigPins.forEach(({ doc, pushpin }) => {
- if (!pushpin[Highlight] && this.map_pinHighlighted.get(pushpin)) {
- this.recolorPin(pushpin);
- this.map_pinHighlighted.delete(pushpin);
- }
- });
- allConfigPins.forEach(({ doc, pushpin }) => {
- if (doc[Highlight] && !this.map_pinHighlighted.get(pushpin)) {
- this.recolorPin(pushpin, 'orange');
- this.map_pinHighlighted.set(pushpin, true);
- }
- });
- },
- { fireImmediately: true }
- );
-
- this._disposers.location = reaction(
- () => ({ lat: this.Document.latitude, lng: this.Document.longitude, zoom: this.Document.map_zoom, mapType: this.Document.map_type }),
- locationObject => {
- // if (this._bingMap.current)
- try {
- locationObject?.zoom &&
- this._bingMap.current?.setView({
- mapTypeId: locationObject.mapType,
- zoom: locationObject.zoom,
- center: new this.MicrosoftMaps.Location(locationObject.lat, locationObject.lng),
- });
- } catch (e) {
- console.log(e);
- }
- },
- { fireImmediately: true }
- );
- };
-
- dragToggle = (e: React.PointerEvent) => {
- let dragClone: HTMLDivElement | undefined;
-
- setupMoveUpEvents(
- e,
- e,
- e => {
- // move event
- if (!dragClone) {
- 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
- }
- dragClone.style.transform = `translate(${e.clientX - 15}px, ${e.clientY - 15}px)`;
- return false;
- },
- 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.ScreenToLocalBoxXf().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;
- }
- target = target.parentElement;
- }
- },
- e => {
- const createPin = () => this.createPushpin(this.Document.latitude, this.Document.longitude, this.Document.map);
- if (this.bingSearchBarContents) {
- this.bingSearch().then(createPin);
- } else createPin();
- }
- );
- };
-
// incrementer: number = 0;
/*
* Creates Pushpin doc and adds it to the list of annotations
@@ -880,7 +573,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
if (createPinForDestination) {
this.createPushpin(destination.center[1], destination.center[0], destination.place_name);
}
- this.temporaryRouteSource = {
+ this._temporaryRouteSource = {
type: 'FeatureCollection',
features: [],
};
@@ -890,10 +583,14 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
// TODO: Display error that can't create route to same location
}, 'createmaproute');
- searchbarKeyDown = (e: any) => e.key === 'Enter' && this.bingSearch();
-
- @observable
- featuresFromGeocodeResults: any[] = [];
+ @action
+ searchbarKeyDown = (e: any) => {
+ if (e.key === 'Enter' && this._featuresFromGeocodeResults) {
+ const center = this._featuresFromGeocodeResults[0]?.center;
+ this._featuresFromGeocodeResults = [];
+ setTimeout(() => center && this._mapRef.current?.flyTo({ center }));
+ }
+ };
@action
addMarkerForFeature = (feature: any) => {
@@ -910,7 +607,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
center: feature.center,
});
}
- this.featuresFromGeocodeResults = [];
+ this._featuresFromGeocodeResults = [];
} else {
// TODO: handle error
}
@@ -922,11 +619,11 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
*/
handleSearchChange = async (searchText: string) => {
const features = await MapboxApiUtility.forwardGeocodeForFeatures(searchText);
- if (features && !this.isAnimating) {
+ if (features && !this._isAnimating) {
runInAction(() => {
- this.settingsOpen = false;
- this.featuresFromGeocodeResults = features;
- this.routeToAnimate = undefined;
+ this._settingsOpen = false;
+ this._featuresFromGeocodeResults = features;
+ this._routeToAnimate = undefined;
});
}
// try {
@@ -946,8 +643,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
@action
handleMapClick = (e: MapLayerMouseEvent) => {
- this.featuresFromGeocodeResults = [];
- this.settingsOpen = false;
+ this._featuresFromGeocodeResults = [];
+ this._settingsOpen = false;
if (this._mapRef.current) {
const features = this._mapRef.current.queryRenderedFeatures(e.point, {
layers: ['map-routes-layer'],
@@ -960,8 +657,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
const routeDoc: Doc | undefined = this.allRoutes.find(routeDoc => routeDoc.title === routeTitle);
this.deselectPinOrRoute(); // TODO: Also deselect route if selected
if (routeDoc) {
- this.selectedPinOrRoute = routeDoc;
- Doc.setDocFilter(this.Document, LinkedTo, `mapRoute=${Field.toScriptString(this.selectedPinOrRoute)}`, 'check');
+ this._selectedPinOrRoute = routeDoc;
+ Doc.setDocFilter(this.Document, LinkedTo, `mapRoute=${Field.toScriptString(this._selectedPinOrRoute)}`, 'check');
// TODO: Recolor route
@@ -1008,7 +705,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
const features = await MapboxApiUtility.reverseGeocodeForFeatures(longitude, latitude);
if (features) {
runInAction(() => {
- this.featuresFromGeocodeResults = features;
+ this._featuresFromGeocodeResults = features;
});
}
@@ -1028,21 +725,18 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
// }
};
- @observable
- currentPopup: PopupInfo | undefined = undefined;
-
@action
handleMarkerClick = (e: MarkerEvent<mapboxgl.Marker, MouseEvent>, pinDoc: Doc) => {
- this.featuresFromGeocodeResults = [];
+ this._featuresFromGeocodeResults = [];
this.deselectPinOrRoute(); // TODO: check this method
- this.selectedPinOrRoute = pinDoc;
+ 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.Document, LinkedTo, `mapPin=${Field.toScriptString(this._selectedPinOrRoute)}`, 'check');
- this.recolorPin(this.selectedPinOrRoute, 'green'); // TODO: check this method
+ this.recolorPin(this._selectedPinOrRoute, 'green'); // TODO: check this method
MapAnchorMenu.Instance.Delete = this.deleteSelectedPinOrRoute;
MapAnchorMenu.Instance.Center = this.centerOnSelectedPin;
@@ -1072,12 +766,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
// })
};
- @observable
- temporaryRouteSource: FeatureCollection = {
- type: 'FeatureCollection',
- features: [],
- };
-
@action
displayRoute = (routeInfoMap: Record<TransportationType, any> | undefined, type: TransportationType) => {
if (routeInfoMap) {
@@ -1096,41 +784,23 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
};
// TODO: Create pin for destination
// TODO: Fly to point where full route will be shown
- this.temporaryRouteSource = newTempRouteSource;
+ this._temporaryRouteSource = newTempRouteSource;
}
};
- @observable
- isAnimating: boolean = false;
-
- @observable
- routeToAnimate: Doc | undefined = undefined;
-
- @observable
- animationPhase: number = 0;
-
- @observable
- finishedFlyTo: boolean = false;
-
@action
setAnimationPhase = (newValue: number) => {
- this.animationPhase = newValue;
+ this._animationPhase = newValue;
};
- @observable
- frameId: number | null = null;
-
@action
setFrameId = (frameId: number) => {
- this.frameId = frameId;
+ this._frameId = frameId;
};
- @observable
- animationUtility: AnimationUtility | null = null;
-
@action
setAnimationUtility = (util: AnimationUtility) => {
- this.animationUtility = util;
+ this._animationUtility = util;
};
@action
@@ -1138,8 +808,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
if (routeDoc) {
MapAnchorMenu.Instance.fadeOut(true);
document.removeEventListener('pointerdown', this.tryHideMapAnchorMenu, true);
- this.featuresFromGeocodeResults = [];
- this.routeToAnimate = routeDoc;
+ this._featuresFromGeocodeResults = [];
+ this._routeToAnimate = routeDoc;
}
};
@@ -1161,29 +831,20 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
@computed
get preAnimationViewState() {
- if (!this.isAnimating) {
+ if (!this._isAnimating) {
return this.mapboxMapViewState;
}
}
- @observable
- isStreetViewAnimation: boolean = false;
-
- @observable
- animationSpeed: AnimationSpeed = AnimationSpeed.MEDIUM;
-
- @observable
- animationLineColor: string = '#ffff00';
-
@action
setAnimationLineColor = (color: ColorResult) => {
- this.animationLineColor = color.hex;
+ this._animationLineColor = color.hex;
};
@action
updateAnimationSpeed = () => {
let newAnimationSpeed: AnimationSpeed;
- switch (this.animationSpeed) {
+ switch (this._animationSpeed) {
case AnimationSpeed.SLOW:
newAnimationSpeed = AnimationSpeed.MEDIUM;
break;
@@ -1197,63 +858,33 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
newAnimationSpeed = AnimationSpeed.MEDIUM;
break;
}
- this.animationSpeed = newAnimationSpeed;
- if (this.animationUtility) {
- this.animationUtility.updateAnimationSpeed(newAnimationSpeed);
+ 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';
- }
+ 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';
+ } // prettier-ignore
}
@computed get animationSpeedIcon(): JSX.Element {
- switch (this.animationSpeed) {
- case AnimationSpeed.SLOW:
- return slowSpeedIcon;
- case AnimationSpeed.MEDIUM:
- return mediumSpeedIcon;
- case AnimationSpeed.FAST:
- return fastSpeedIcon;
- default:
- return mediumSpeedIcon;
- }
+ switch (this._animationSpeed) {
+ case AnimationSpeed.SLOW: return slowSpeedIcon;
+ case AnimationSpeed.MEDIUM: return mediumSpeedIcon;
+ case AnimationSpeed.FAST: return fastSpeedIcon;
+ default: return mediumSpeedIcon;
+ } // prettier-ignore
}
@action
toggleIsStreetViewAnimation = () => {
- const newVal = !this.isStreetViewAnimation;
- this.isStreetViewAnimation = newVal;
- if (this.animationUtility) {
- this.animationUtility.updateIsStreetViewAnimation(newVal);
- }
- };
-
- @observable
- dynamicRouteFeature: Feature<Geometry, GeoJsonProperties> = {
- type: 'Feature',
- properties: {},
- geometry: {
- type: 'LineString',
- coordinates: [],
- },
- };
-
- @observable
- path: turf.helpers.Feature<turf.helpers.LineString, turf.helpers.Properties> = {
- type: 'Feature',
- geometry: {
- type: 'LineString',
- coordinates: [],
- },
- properties: {},
+ const newVal = !this._isStreetViewAnimation;
+ this._isStreetViewAnimation = newVal;
+ this._animationUtility?.updateIsStreetViewAnimation(newVal);
};
getFeatureFromRouteDoc = (routeDoc: Doc): Feature<Geometry, GeoJsonProperties> => {
@@ -1272,19 +903,19 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
@action
playAnimation = (status: AnimationStatus) => {
- if (!this._mapRef.current || !this.routeToAnimate) {
+ if (!this._mapRef.current || !this._routeToAnimate) {
return;
}
- this.animationPhase = status === AnimationStatus.RESUME ? this.animationPhase : 0;
- this.frameId = AnimationStatus.RESUME ? this.frameId : null;
- this.finishedFlyTo = AnimationStatus.RESUME ? this.finishedFlyTo : false;
+ 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._settingsOpen = false;
this.path = path;
- this.isAnimating = true;
+ this._isAnimating = true;
runInAction(() => {
return new Promise<void>(async resolve => {
@@ -1293,18 +924,11 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
lat: this.selectedRouteCoordinates[0][1],
};
- 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 animationUtil = new AnimationUtility(targetLngLat, this.selectedRouteCoordinates, this._isStreetViewAnimation, this._animationSpeed, this._showTerrain, this._mapRef.current);
+ runInAction(() => this.setAnimationUtility(animationUtil));
- const updateAnimationPhase = (newAnimationPhase: number) => {
- this.setAnimationPhase(newAnimationPhase);
- };
+ const updateFrameId = (newFrameId: number) => this.setFrameId(newFrameId);
+ const updateAnimationPhase = (newAnimationPhase: number) => this.setAnimationPhase(newAnimationPhase);
if (status !== AnimationStatus.RESUME) {
const result = await animationUtil.flyInAndRotate({
@@ -1324,9 +948,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
console.log('Altitude: ', result.altitude);
}
- runInAction(() => {
- this.finishedFlyTo = true;
- });
+ 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({
@@ -1335,7 +957,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
// startBearing: -20,
// startAltitude: this.isStreetViewAnimation ? 80 : 12000,
// pitch: this.isStreetViewAnimation ? 80: 50,
- currentAnimationPhase: this.animationPhase,
+ currentAnimationPhase: this._animationPhase,
updateAnimationPhase,
updateFrameId,
});
@@ -1353,7 +975,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
});
setTimeout(() => {
- this.isStreetViewAnimation = false;
+ this._isStreetViewAnimation = false;
resolve();
}, 10000);
});
@@ -1362,27 +984,27 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
@action
pauseAnimation = () => {
- if (this.frameId && this.animationPhase > 0) {
- window.cancelAnimationFrame(this.frameId);
- this.frameId = null;
- this.isAnimating = false;
+ if (this._frameId && this._animationPhase > 0) {
+ window.cancelAnimationFrame(this._frameId);
+ this._frameId = null;
+ this._isAnimating = false;
}
};
@action
stopAnimation = (close: boolean) => {
- if (this.frameId) {
- window.cancelAnimationFrame(this.frameId);
+ if (this._frameId) {
+ window.cancelAnimationFrame(this._frameId);
}
- this.animationPhase = 0;
- this.frameId = null;
- this.finishedFlyTo = false;
- this.isAnimating = false;
+ 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.animationUtility = null;
+ this._animationSpeed = AnimationSpeed.MEDIUM;
+ this._isStreetViewAnimation = false;
+ this._routeToAnimate = undefined;
+ this._animationUtility = null;
}
};
@@ -1390,21 +1012,21 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
return (
<>
<IconButton
- tooltip={this.isAnimating && this.finishedFlyTo ? 'Pause Animation' : 'Play Animation'}
+ tooltip={this._isAnimating && this._finishedFlyTo ? 'Pause Animation' : 'Play Animation'}
onPointerDown={() => {
- if (this.isAnimating && this.finishedFlyTo) {
+ if (this._isAnimating && this._finishedFlyTo) {
this.pauseAnimation();
- } else if (this.animationPhase > 0) {
+ } else if (this._animationPhase > 0) {
this.playAnimation(AnimationStatus.RESUME); // Resume from the current phase
} else {
this.playAnimation(AnimationStatus.START); // Play from the beginning
}
}}
- icon={this.isAnimating && this.finishedFlyTo ? <FontAwesomeIcon icon={faPause as IconLookup} /> : <FontAwesomeIcon icon={faPlay as IconLookup} />}
+ icon={this._isAnimating && this._finishedFlyTo ? <FontAwesomeIcon icon={faPause as IconLookup} /> : <FontAwesomeIcon icon={faPlay as IconLookup} />}
color="black"
size={Size.MEDIUM}
/>
- {this.isAnimating && this.finishedFlyTo && (
+ {this._isAnimating && this._finishedFlyTo && (
<IconButton
tooltip="Restart animation"
onPointerDown={() => {
@@ -1420,7 +1042,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
<>
<div className="animation-suboptions">
<div>|</div>
- <FormControlLabel className="first-person-label" label="1st person animation:" labelPlacement="start" control={<Checkbox color="success" checked={this.isStreetViewAnimation} onChange={this.toggleIsStreetViewAnimation} />} />
+ <FormControlLabel className="first-person-label" 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>
@@ -1436,26 +1058,17 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
@action
hideRoute = () => {
- this.temporaryRouteSource = {
+ this._temporaryRouteSource = {
type: 'FeatureCollection',
features: [],
};
};
- @observable
- settingsOpen: boolean = false;
-
- @observable
- mapStyle: string = 'mapbox://styles/mapbox/standard';
-
- @observable
- showTerrain: boolean = true;
-
@action
toggleSettings = () => {
- if (!this.isAnimating && this.animationPhase == 0) {
- this.featuresFromGeocodeResults = [];
- this.settingsOpen = !this.settingsOpen;
+ if (!this._isAnimating && this._animationPhase == 0) {
+ this._featuresFromGeocodeResults = [];
+ this._settingsOpen = !this._settingsOpen;
}
};
@@ -1500,14 +1113,10 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
@action
onStepZoomChange = (increment: boolean) => {
if (this._mapRef.current) {
- let newZoom: number;
- if (increment) {
- console.log('inc');
- newZoom = Math.min(16, this.mapboxMapViewState.zoom + 1);
- } else {
- console.log('dec');
- newZoom = Math.max(0, this.mapboxMapViewState.zoom - 1);
- }
+ const newZoom = increment //
+ ? Math.min(16, this.mapboxMapViewState.zoom + 1)
+ : Math.max(0, this.mapboxMapViewState.zoom - 1);
+
this._mapRef.current.setZoom(newZoom);
this.dataDoc.map_zoom = newZoom;
}
@@ -1523,7 +1132,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
};
@action
- toggleShowTerrain = () => (this.showTerrain = !this.showTerrain);
+ toggleShowTerrain = () => (this._showTerrain = !this._showTerrain);
getMarkerIcon = (pinDoc: Doc): JSX.Element | null => {
const markerType = StrCast(pinDoc.markerType);
@@ -1532,25 +1141,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
return MarkerIcons.getFontAwesomeIcon(markerType, '2x', markerColor) ?? null;
};
- static _firstRender = true;
- static _rerenderDelay = 500;
- _rerenderTimeout: any;
+ _textRef = React.createRef<any>();
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];
- if (MapBox._rerenderDelay) {
- // prettier-ignore
- this._rerenderTimeout = this._rerenderTimeout ??
- setTimeout(action(() => {
- if ((window as any).Microsoft?.Maps?.Internal._WorkDispatcher) {
- MapBox._rerenderDelay = 0;
- }
- this._rerenderTimeout = undefined;
- this.Document[DocCss] = this.Document[DocCss] + 1;
- }), MapBox._rerenderDelay);
- return null;
- }
const scale = this._props.NativeDimScaling?.() || 1;
const parscale = scale === 1 ? 1 : this.ScreenToLocalBoxXf().Scale ?? 1;
@@ -1560,20 +1152,21 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
<div
className="mapBox-wrapper"
onWheel={e => e.stopPropagation()}
- onPointerDown={async e => {
- e.button === 0 && !e.ctrlKey && e.stopPropagation();
- }}
+ onPointerDown={e => e.button === 0 && !e.ctrlKey && e.stopPropagation()}
style={{ transformOrigin: 'top left', transform: `scale(${scale})`, width: `calc(100% - ${this.sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}>
<div style={{ mixBlendMode: 'multiply' }}>{renderAnnotations(this.transparentFilter)}</div>
{renderAnnotations(this.opaqueFilter)}
{SnappingManager.IsDragging ? null : renderAnnotations()}
- {!this.routeToAnimate && (
+ {!this._routeToAnimate && (
<div className="mapBox-searchbar" style={{ width: `${100 / scale}%`, zIndex: 1, position: 'relative', background: 'lightGray' }}>
- <TextField fullWidth placeholder="Enter a location" onChange={(e: any) => this.handleSearchChange(e.target.value)} />
+ <TextField ref={this._textRef} fullWidth placeholder="Enter a location" onKeyDown={this.searchbarKeyDown} 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 style={{ opacity: 0 }}>
+ <IconButton icon={<FontAwesomeIcon icon={faGear as IconLookup} size="1x" />} type={Type.TERT} onClick={e => this.toggleSettings()} />
+ </div>
</div>
)}
- {this.settingsOpen && !this.routeToAnimate && (
+ {this._settingsOpen && !this._routeToAnimate && (
<div className="mapbox-settings-panel" style={{ right: `${0 + this.sidebarWidth()}px` }}>
<div className="mapbox-style-select">
<div>Map Style:</div>
@@ -1605,21 +1198,21 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
</div>
<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 && (
+ {this._routeToAnimate && (
<div className="animation-panel" style={{ width: this.sidebarWidth() === 0 ? '100%' : `calc(100% - ${this.sidebarWidth()}px)` }}>
- <div id="route-to-animate-title">{StrCast(this.routeToAnimate.title)}</div>
+ <div id="route-to-animate-title">{StrCast(this._routeToAnimate.title)}</div>
<div className="route-animation-options">{this.getRouteAnimationOptions()}</div>
</div>
)}
- {this.featuresFromGeocodeResults.length > 0 && (
+ {this._featuresFromGeocodeResults.length > 0 && (
<div className="mapbox-geocoding-search-results">
- <React.Fragment>
+ <>
<h4>Choose a location for your pin: </h4>
- {this.featuresFromGeocodeResults
+ {this._featuresFromGeocodeResults
.filter(feature => feature.place_name)
.map((feature, idx) => (
<div
@@ -1632,14 +1225,14 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
<div className="search-result-place-name">{feature.place_name}</div>
</div>
))}
- </React.Fragment>
+ </>
</div>
)}
<MapProvider>
<MapboxMap
ref={this._mapRef}
mapboxAccessToken={MAPBOX_ACCESS_TOKEN}
- viewState={this.isAnimating || this.routeToAnimate ? undefined : { ...this.mapboxMapViewState, width: NumCast(this.layoutDoc._width), height: NumCast(this.layoutDoc._height) }}
+ viewState={this._isAnimating || this._routeToAnimate ? undefined : { ...this.mapboxMapViewState, width: NumCast(this.layoutDoc._width), height: NumCast(this.layoutDoc._height) }}
mapStyle={this.dataDoc.map_style ? StrCast(this.dataDoc.map_style) : 'mapbox://styles/mapbox/streets-v11'}
style={{
position: 'absolute',
@@ -1649,20 +1242,22 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
width: NumCast(this.layoutDoc._width) * parscale,
height: NumCast(this.layoutDoc._height) * parscale,
}}
- initialViewState={this.isAnimating ? undefined : this.mapboxMapViewState}
+ initialViewState={this._isAnimating ? undefined : this.mapboxMapViewState}
onZoom={this.onMapZoom}
onMove={this.onMapMove}
onClick={this.handleMapClick}
onDblClick={this.handleMapDblClick}
- terrain={this.showTerrain ? { source: 'mapbox-dem', exaggeration: 2.0 } : undefined}>
+ 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="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._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
@@ -1670,7 +1265,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
type="line"
source="animated-route"
paint={{
- 'line-color': this.animationLineColor,
+ 'line-color': this._animationLineColor,
'line-width': 5,
}}
/>
@@ -1722,10 +1317,9 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
)}
<>
- {!this.isAnimating &&
- this.animationPhase == 0 &&
- this.allPushpins
- // .filter(anno => !anno.layout_unrendered)
+ {!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)}
diff --git a/src/client/views/nodes/MapBox/MapPushpinBox.tsx b/src/client/views/nodes/MapBox/MapPushpinBox.tsx
index fc5b4dd18..8ebc90157 100644
--- a/src/client/views/nodes/MapBox/MapPushpinBox.tsx
+++ b/src/client/views/nodes/MapBox/MapPushpinBox.tsx
@@ -1,7 +1,7 @@
import * as React from 'react';
import { ViewBoxBaseComponent } from '../../DocComponent';
import { FieldView, FieldViewProps } from '../FieldView';
-import { MapBox } from './MapBox';
+import { MapBoxContainer } from '../MapboxMapBox/MapboxContainer';
/**
* Map Pushpin doc class
@@ -18,7 +18,7 @@ export class MapPushpinBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
get mapBoxView() {
- return this.DocumentView?.()?.containerViewPath?.().lastElement()?.ComponentView as MapBox;
+ return this.DocumentView?.()?.containerViewPath?.().lastElement()?.ComponentView as MapBoxContainer;
}
get mapBox() {
return this.DocumentView?.().containerViewPath?.().lastElement()?.Document;