Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rebase deck gl poc on main #1027

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6f98019
Deck.gl proof of work
florencelauer Apr 18, 2023
b82d444
Replace main map with a Deck.gl layer
tahini Nov 10, 2023
abdaa8e
Add MapLibre as the base map
davidmurray Nov 15, 2023
845990d
Allow showing an XYZ tile layer
davidmurray Nov 15, 2023
96e0f0a
Allow changing map background via the preferences
davidmurray Oct 27, 2023
fd928ae
Remove references to mapbox in .env file
davidmurray Nov 15, 2023
7602df5
deck.gl: Change types of the map layer
tahini Nov 15, 2023
f3a51e5
Make AnimatedArrowPathLayer work
davidmurray Nov 15, 2023
dbb4174
LineLayer's should just be PathLayer, not TripsLayer
davidmurray Nov 16, 2023
63a7ae2
deck.gl: Support events on map and map layers
tahini Nov 15, 2023
bca59ea
deck.gl: Save zoom and center to user preferences
tahini Dec 4, 2023
f5944fe
deck.gl: Add an updateCount to trigger map updates on layers
tahini Dec 18, 2023
dde11d3
deck.gl: Set styles for circle layers
tahini Dec 18, 2023
2c36e50
deck.gl: Add comments and fix direction of animated path
tahini Jan 10, 2024
b430d4c
deck.gl: Set styles for line layers
tahini Jan 9, 2024
5979208
deck.gl: Set styles for polygon layers
tahini Jan 12, 2024
2823271
deck.gl: Remove the original proof of concept
tahini Jan 17, 2024
c5d3ff3
deck.gl: Improve performance and look of animated path layer
kaligrafy Jan 18, 2024
c4e7a2e
deck.gl: Support filtering of features based on zoom
tahini Jan 19, 2024
d5521da
deck.gl: Support filtering lines and agencies
tahini Jan 19, 2024
e326538
deck.gl: Remove dependencies to mapbox
tahini Jan 23, 2024
03817f9
preferences: Add an option to enable map animations
tahini Mar 11, 2024
aba4eda
animated path: Allow to disable animations for the layer
tahini Mar 11, 2024
3172e9a
deck.gl: Support the max/minRadiusPixels properties
tahini Jun 7, 2024
8cc4138
Fix formatting with `yarn format`
tahini Jun 7, 2024
28db280
map: Add a preference for the opacity of xyz tile layer
tahini Jun 7, 2024
119df36
rebase Deck GL branch on Main
kaligrafy Aug 1, 2024
78ccd7f
Merge branch 'main' into rebaseDeckGlPocOnMain
kaligrafy Aug 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .env.docker
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ EXPRESS_SESSION_SECRET_KEY=DefaultDockerSessionKey
# Host and port for the trRouting server
#TR_ROUTING_HOST_URL=http://locahost
#TR_ROUTING_HOST_PORT=4000
# Required for the mapbox map
MAPBOX_ACCESS_TOKEN=MYMAPBOXACCESSTOKEN
MAPBOX_USER_ID=mapbox
MAPBOX_STYLE_ID=dark-v10
#MAGIC_LINK_SECRET_KEY=MYVERYLONGSECRETKEYTOENCRYPTTOKENTOSENDTOUSERFORPASSWORDLESSLOGIN
#CUSTOM_RASTER_TILES_XYZ_URL=https://exampltest/{z}/{x}/{y}
#CUSTOM_RASTER_TILES_MIN_ZOOM=8
Expand Down
4 changes: 0 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ GOOGLE_OAUTH_SECRET_KEY=GOOGLEOAUTHSECRETKEY
# To support Facebook login
FACEBOOK_APP_ID=FACEBOOKAPPID
FACEBOOK_APP_SECRET=FACEBOOKAPPSECRET
# Required for the mapbox map
MAPBOX_ACCESS_TOKEN=MYMAPBOXACCESSTOKEN
MAPBOX_USER_ID=mapbox
MAPBOX_STYLE_ID=dark-v10
#MAGIC_LINK_SECRET_KEY=MYVERYLONGSECRETKEYTOENCRYPTTOKENTOSENDTOUSERFORPASSWORDLESSLOGIN
#CUSTOM_RASTER_TILES_XYZ_URL=https://exampltest/{z}/{x}/{y}
#CUSTOM_RASTER_TILES_MIN_ZOOM=8
Expand Down
13 changes: 12 additions & 1 deletion locales/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,17 @@
"DefaultWalkingSpeedKph": "Default walking speed (km/h)",
"DefaultWalkingSpeedKphHelp": "Walking speed varies according to age and gender between 3 km/h (elderly people and young children) and 7 km/h (young and/or very active people). Men are on average a little faster than women and in general, walking speed decreases with age. The speed of a person in a manual wheelchair varies between 2 and 3 km/h depending on physical strength.",
"ExperimentalFeatures": "Experimental features",
"Map": "Map preferences",
"MapStyle": "Map background",
"MapStyleHelp": "Vector tile layer to use as map background",
"RasterTileLayerOpacity": "Raster/photo tile layer opacity",
"RasterTileLayerOpacityHelp": "Percentage opacity of the raster/photo tile layer, if available (between 0 and 100). An opacity of 0 will not display this layer.",
"MapPrettyDisplay": "Display pretty lines and nodes on map",
"mapStyles": {
"osmBright": "OpenStreetMap",
"positron": "Light (positron)",
"darkMatter": "Dark (dark matter)"
},
"transit": {
"nodes": {}
},
Expand All @@ -279,7 +289,8 @@
},
"DateTimeFormat": "Date/Time format",
"DateTimeFormat24H": "24 hours ({{formatted}})",
"DateTimeFormat12H": "12 hours ({{formatted}})"
"DateTimeFormat12H": "12 hours ({{formatted}})",
"EnableMapAnimations": "Enable map animations"
},
"ShowingNofX": "Showing {{n}} of {{x}} results",
"PageNofX": "Page {{n}} of {{x}}",
Expand Down
13 changes: 12 additions & 1 deletion locales/fr/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,17 @@
"DefaultWalkingSpeedKph": "Vitesse de marche par défaut (km/h)",
"DefaultWalkingSpeedKphHelp": "La vitesse de marche varie selon l'âge et le genre entre 3 km/h (personnes âges et jeunes enfants) et 7 km/h (personnes jeunes et/ou très actives). Les hommes sont en moyenne un peu plus rapides que les femmes et de manière générale, la vitesse de marche diminue avec l'âge. La vitesse d'une personne en chaise roulante manuelle varie entre 2 et 3 km/h selon la force physique.",
"ExperimentalFeatures": "Fonctionnalités expérimentales",
"Map": "Carte",
"MapStyle": "Fond de carte",
"MapStyleHelp": "Couche vectorielle de fond de carte",
"RasterTileLayerOpacity": "Opacité de la couche photo/raster",
"RasterTileLayerOpacityHelp": "Opacité de la couche photo/raster, si disponible, en pourcentage (entre 0 et 100). Une opacité de 0 n'affichera pas cette couche.",
"MapPrettyDisplay": "Affichage esthétique des lignes et noeuds sur la carte",
"mapStyles": {
"osmBright": "OpenStreetMap",
"positron": "Clair (positron)",
"darkMatter": "Foncé (dark matter)"
},
"transit": {
"nodes": {}
},
Expand All @@ -279,7 +289,8 @@
},
"DateTimeFormat": "Format de date/heure",
"DateTimeFormat24H": "24 heures ({{formatted}})",
"DateTimeFormat12H": "12 heures ({{formatted}})"
"DateTimeFormat12H": "12 heures ({{formatted}})",
"EnableMapAnimations": "Activer les animations de cartes"
},
"ShowingNofX": "{{n}} de {{x}} résultats",
"PageNofX": "Page {{n}} de {{x}}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe('OSRM Mode tests', function() {
points: [origin, destination1] };

fetchMock.mockOnce('{ "status"');
await expect(aMode.route(params)).rejects.toThrow('invalid json response body at reason: Unexpected end of JSON input');
await expect(aMode.route(params)).rejects.toThrow('invalid json response body at reason: Expected \':\'');

});

Expand Down
23 changes: 14 additions & 9 deletions packages/chaire-lib-common/src/config/defaultPreferences.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ export interface PreferencesModel {
defaultSection: string;
infoPanelPosition: string;
dateTimeFormat: string;
mapStyleURL: string;
mapTileLayerOpacity: number;
sections: {
[key: string]: {
[key: string]: SectionDescription;
Expand All @@ -37,6 +39,8 @@ const defaultPreferences: PreferencesModel = {
defaultSection: 'agencies',
infoPanelPosition: 'right',
dateTimeFormat: 'YYYY-MM-DD HH:mm',
mapStyleURL: 'https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json',
mapTileLayerOpacity: 0.5,
sections: {
transition: {
agencies: {
Expand Down Expand Up @@ -100,6 +104,7 @@ const defaultPreferences: PreferencesModel = {
map: {
center: [config.mapDefaultCenter.lon, config.mapDefaultCenter.lat],
zoom: 10,
enableMapAnimations: true,
layers: {
simulations: ['aggregatedOD', 'odTripsProfile', 'transitStations', 'transitNodes'],
agencies: [
Expand Down Expand Up @@ -564,20 +569,20 @@ const defaultPreferences: PreferencesModel = {
maxTotalTravelTimeSeconds: 10800,
walkingSpeedMps: 1.3888888888,
walkingSpeedFactor: 1.0, // walking travel times are weighted using this factor: Example: > 1.0 means faster walking, < 1.0 means slower walking
originLocationColor: 'rgba(140, 212, 0, 1.0)',
destinationLocationColor: 'rgba(212, 35, 14, 1.0)',
walkingSegmentsColor: 'rgba(160,160,160,1.0)',
originLocationColor: '#8cd400',
destinationLocationColor: '#d4230e',
walkingSegmentsColor: '#a0a0a0',
walking: {
color: 'rgba(255, 238, 0,1.0)'
color: '#ffee00'
},
cycling: {
color: 'rgba(0, 204, 51,1.0)'
color: '#00cc33'
},
driving: {
color: 'rgba(229, 45, 0,1.0)'
color: '#e52d00'
},
default: {
color: 'rgba(160,160,160,1.0)'
color: '#a0a0a0'
}
},
transitAccessibilityMap: {
Expand All @@ -594,8 +599,8 @@ const defaultPreferences: PreferencesModel = {
walkingSpeedMps: 1.3888888888,
walkingSpeedFactor: 1.0, // walking travel times are weighted using this factor: Example: > 1.0 means faster walking, < 1.0 means slower walking
maxTotalTravelTimeSeconds: 1800,
locationColor: 'rgba(47, 138, 243, 1.0)',
polygonColor: 'rgba(47, 138, 243, 0.4)'
locationColor: '#2f8af3',
polygonColor: '#2f8af366'
},
transitOdTrips: {
minWaitingTimeSeconds: 180,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,5 @@ export const getPointCoordinates = (geojson: GeoJSON.GeoJSON): number[] | undefi
}
return undefined;
};

export const emptyFeatureCollection = { type: 'FeatureCollection', features: [] } as GeoJSON.FeatureCollection;
7 changes: 4 additions & 3 deletions packages/chaire-lib-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
"@fortawesome/fontawesome-svg-core": "^1.2.32",
"@fortawesome/free-solid-svg-icons": "^5.15.2",
"@fortawesome/react-fontawesome": "^0.1.11",
"@mapbox/mapbox-gl-draw": "^1.3.0",
"@turf/helpers": "^6.1.4",
"@turf/length": "^6.0.2",
"@turf/turf": "^6.3.0",
Expand All @@ -35,6 +34,7 @@
"chaire-lib-common": "^0.2.2",
"child_process": "^1.0.2",
"date-fns": "^2.30.0",
"deck.gl": "^8.9.32",
"font-awesome": "^4.7.0",
"geojson": "^0.5.0",
"history": "^4.9.0",
Expand All @@ -43,7 +43,7 @@
"i18next-http-backend": "^2.1.0",
"json-loader": "^0.5.7",
"lodash": "^4.17.21",
"mapbox-gl": "chairemobilite/mapbox-gl-js#39bbf9aeb1859424e29cff2584715fddc9d018b9",
"mjolnir.js": "^2.7.0",
"moment": "^2.29.4",
"moment-business-days": "^1.2.0",
"papaparse": "^5.3.1",
Expand Down Expand Up @@ -76,7 +76,6 @@
"@types/geojson": "^7946.0.7",
"@types/jest": "^29.5.12",
"@types/lodash": "^4.14.198",
"@types/mapbox-gl": "^2.3.1",
"@types/osrm": "^5.22.0",
"@types/react-loadable": "^5.5.6",
"@types/react-redux": "^7.1.9",
Expand All @@ -88,6 +87,7 @@
"@typescript-eslint/parser": "^6.21.0",
"copyfiles": "^2.4.1",
"cross-env": "^7.0.2",
"deck.gl": "^8.9.32",
"dotenv": "^8.2.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.4",
Expand All @@ -99,6 +99,7 @@
"jest-each": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-fetch-mock": "^3.0.3",
"mjolnir.js": "^2.7.0",
"mockdate": "^3.0.2",
"prettier-eslint-cli": "^8.0.1",
"react-select-event": "^5.0.0",
Expand Down
153 changes: 108 additions & 45 deletions packages/chaire-lib-frontend/src/services/map/IMapEventHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,51 +4,114 @@
* This file is licensed under the MIT License.
* License text available at https://opensource.org/licenses/MIT
*/
import MapboxGL from 'mapbox-gl';
import { MjolnirEvent } from 'mjolnir.js';
import { PickingInfo, Deck } from 'deck.gl/typed';

// TODO: Make this independent of mapbox eventually. For now, we use mapbox
// types, as they are already defined, when we have more implementations, we can
// review this
type MapEventHandler = (e: MapboxGL.MapMouseEvent) => void;
type MapLayerEventHandler = (e: MapboxGL.MapLayerMouseEvent & MapboxGL.EventData) => void;
export type MapCallbacks = { pickMultipleObjects: typeof Deck.prototype.pickMultipleObjects };
export type PointInfo = { coordinates: number[]; pixel: [number, number] };
export type MapEventHandler = (pointInfo: PointInfo, e: MjolnirEvent, mapCallbacks: MapCallbacks) => void;
export type MapSelectEventHandler = (pickInfo: PickingInfo[], e: MjolnirEvent, mapCallbacks: MapCallbacks) => void;
export type MapLayerEventHandler = (pickInfo: PickingInfo, e: MjolnirEvent, mapCallbacks: MapCallbacks) => void;
export type TooltipEventHandler = (
pickInfo: PickingInfo,
mapCallbacks: MapCallbacks
) => string | undefined | { text: string; containsHtml: boolean };

export type layerEventNames = 'onLeftClick' | 'onRightClick' | 'onDragStart' | 'onDrag' | 'onDragEnd' | 'onHover';
export type tooltipEventNames = 'onTooltip';
export type mapEventNames = 'onLeftClick' | 'onRightClick';

export type MapEventHandlerDescriptor = {
/** Type for handlers that only require the layer to be active */
type: 'map';
eventName: mapEventNames;
/**
* Condition function for which this handler applies. It will be checked
* before actually calling the handler, so the handler can assume this is
* true.
*
* TODO: This should depend on some application's state or context, that
* should be passed here. For now, we pass the active section and the rest
* can be accessed through the serviceLocator
* */
condition?: (activeSection: string) => boolean;
/**
* The event handler
*/
handler: MapEventHandler;
};

/**
* Type of event called when no layer event was handled on a specific element,
* but there might be features under the event location. Ideal to handle
* multiple features, as `MapLayerEventHandlerDescriptor` will only handle the
* top-most selected element
*/
export type MapSelectEventHandlerDescriptor = {
/** Type for handlers that only require the layer to be active */
type: 'mapSelect';
layerName: string;
eventName: mapEventNames;
/**
* Condition function for which this handler applies. It will be checked
* before actually calling the handler, so the handler can assume this is
* true.
*
* TODO: This should depend on some application's state or context, that
* should be passed here. For now, we pass the active section and the rest
* can be accessed through the serviceLocator
* */
condition?: (activeSection: string) => boolean;
/**
* The event handler
*/
handler: MapSelectEventHandler;
};

export type MapLayerEventHandlerDescriptor = {
/** Type for handler that require selected features */
type: 'layer';
layerName: string;
eventName: layerEventNames;
/**
* Condition function for which this handler applies. It will be checked
* before actually calling the handler, so the handler can assume this is
* true.
*
* TODO: This should depend on some application's state or context, that
* should be passed here. For now, we pass the active section and the rest
* can be accessed through the serviceLocator
* */
condition?: (activeSection: string) => boolean;
/**
* The event handler
*/
handler: MapLayerEventHandler;
};

export type TooltipEventHandlerDescriptor = {
/** Type for handler that require selected features */
type: 'tooltip';
layerName: string;
eventName: tooltipEventNames;
/**
* Condition function for which this handler applies. It will be checked
* before actually calling the handler, so the handler can assume this is
* true.
*
* TODO: This should depend on some application's state or context, that
* should be passed here. For now, we pass the active section and the rest
* can be accessed through the serviceLocator
* */
condition?: (activeSection: string) => boolean;
/**
* The event handler
*/
handler: TooltipEventHandler;
};

export type MapEventHandlerDescription =
| {
/** Type for handler that require selected features */
type: 'layer';
layerName: string;
eventName: keyof MapboxGL.MapLayerEventType;
/**
* Condition function for which this handler applies. It will be checked
* before actually calling the handler, so the handler can assume this is
* true.
*
* TODO: This should depend on some application's state or context, that
* should be passed here. For now, we pass the active section and the rest
* can be accessed through the serviceLocator
* */
condition?: (activeSection: string) => boolean;
/**
* The event handler
*/
handler: MapLayerEventHandler;
}
| {
/** Type for handlers that only require the layer to be active */
type: 'map';
eventName: keyof MapboxGL.MapEventType;
/**
* Condition function for which this handler applies. It will be checked
* before actually calling the handler, so the handler can assume this is
* true.
*
* TODO: This should depend on some application's state or context, that
* should be passed here. For now, we pass the active section and the rest
* can be accessed through the serviceLocator
* */
condition?: (activeSection: string) => boolean;
/**
* The event handler
*/
handler: MapEventHandler;
};
| MapEventHandlerDescriptor
| MapLayerEventHandlerDescriptor
| TooltipEventHandlerDescriptor
| MapSelectEventHandlerDescriptor;
Loading
Loading