Skip to content

Commit

Permalink
added ability for user to toggle node clusters in the map interface. …
Browse files Browse the repository at this point in the history
…Vastly increases performance for large numbers of nodes
  • Loading branch information
ASC95 committed Feb 28, 2024
1 parent a8ede68 commit 3983cc6
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 19 deletions.
2 changes: 1 addition & 1 deletion omf/static/geoJsonMap/v3/featureEditModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -1007,7 +1007,7 @@ function zoom(observables) {
const layer = Object.values(observable.getObservers().filter(ob => ob instanceof LeafletLayer)[0].getLayer()._layers)[0];
if (observable.isNode()) {
const [lon, lat] = structuredClone(observable.getCoordinates());
// - This is the max zoom without losing the map
// - The max zoom level without losing the map is 19
LeafletLayer.map.flyTo([lat, lon], 19, {duration: .3});
if (!layer.isPopupOpen()) {
layer.openPopup();
Expand Down
16 changes: 4 additions & 12 deletions omf/static/geoJsonMap/v3/leafletLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ class LeafletLayer { // implements ObserverInterface
#controller; // ControllerInterface instance
#layer; // - Leaflet layer
#observable; // - ObservableInterface instance
static lineLayers = L.featureGroup();
static map;
static control;
static nodeLayers = L.featureGroup();
static lineLayers = L.featureGroup();
static parentChildLineLayers = L.featureGroup();
static childNodeLayers = L.featureGroup();

/**
* @param {Feature} observable - an ObservableInterface instance
Expand Down Expand Up @@ -90,11 +90,7 @@ class LeafletLayer { // implements ObserverInterface
layer.remove();
// - Need to explicitly remove the underlying layer from its LayerGroup
if (observable.isNode()) {
if (observable.isChild()) {
LeafletLayer.childNodeLayers.removeLayer(this.#layer);
} else {
LeafletLayer.nodeLayers.removeLayer(this.#layer);
}
LeafletLayer.nodeLayers.removeLayer(this.#layer);
} else if (observable.isLine()) {
if (observable.isParentChildLine()) {
LeafletLayer.parentChildLineLayers.removeLayer(this.#layer);
Expand Down Expand Up @@ -177,11 +173,7 @@ class LeafletLayer { // implements ObserverInterface
}
const ll = new LeafletLayer(observable, controller);
if (observable.isNode()) {
if (observable.isChild()) {
LeafletLayer.childNodeLayers.addLayer(ll.getLayer());
} else {
LeafletLayer.nodeLayers.addLayer(ll.getLayer());
}
LeafletLayer.nodeLayers.addLayer(ll.getLayer());
} else if (observable.isLine()) {
if (observable.isParentChildLine()) {
LeafletLayer.parentChildLineLayers.addLayer(ll.getLayer());
Expand Down
60 changes: 60 additions & 0 deletions omf/static/geoJsonMap/v3/lib/MarkerCluster.Default.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
.marker-cluster-small {
background-color: rgba(181, 226, 140, 0.6);
}
.marker-cluster-small div {
background-color: rgba(110, 204, 57, 0.6);
}

.marker-cluster-medium {
background-color: rgba(241, 211, 87, 0.6);
}
.marker-cluster-medium div {
background-color: rgba(240, 194, 12, 0.6);
}

.marker-cluster-large {
background-color: rgba(253, 156, 115, 0.6);
}
.marker-cluster-large div {
background-color: rgba(241, 128, 23, 0.6);
}

/* IE 6-8 fallback colors */
.leaflet-oldie .marker-cluster-small {
background-color: rgb(181, 226, 140);
}
.leaflet-oldie .marker-cluster-small div {
background-color: rgb(110, 204, 57);
}

.leaflet-oldie .marker-cluster-medium {
background-color: rgb(241, 211, 87);
}
.leaflet-oldie .marker-cluster-medium div {
background-color: rgb(240, 194, 12);
}

.leaflet-oldie .marker-cluster-large {
background-color: rgb(253, 156, 115);
}
.leaflet-oldie .marker-cluster-large div {
background-color: rgb(241, 128, 23);
}

.marker-cluster {
background-clip: padding-box;
border-radius: 20px;
}
.marker-cluster div {
width: 30px;
height: 30px;
margin-left: 5px;
margin-top: 5px;

text-align: center;
border-radius: 15px;
font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif;
}
.marker-cluster span {
line-height: 30px;
}
14 changes: 14 additions & 0 deletions omf/static/geoJsonMap/v3/lib/MarkerCluster.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.leaflet-cluster-anim .leaflet-marker-icon, .leaflet-cluster-anim .leaflet-marker-shadow {
-webkit-transition: -webkit-transform 0.3s ease-out, opacity 0.3s ease-in;
-moz-transition: -moz-transform 0.3s ease-out, opacity 0.3s ease-in;
-o-transition: -o-transform 0.3s ease-out, opacity 0.3s ease-in;
transition: transform 0.3s ease-out, opacity 0.3s ease-in;
}

.leaflet-cluster-spider-leg {
/* stroke-dashoffset (duration and function) should match with leaflet-marker-icon transform in order to track it exactly */
-webkit-transition: -webkit-stroke-dashoffset 0.3s ease-out, -webkit-stroke-opacity 0.3s ease-in;
-moz-transition: -moz-stroke-dashoffset 0.3s ease-out, -moz-stroke-opacity 0.3s ease-in;
-o-transition: -o-stroke-dashoffset 0.3s ease-out, -o-stroke-opacity 0.3s ease-in;
transition: stroke-dashoffset 0.3s ease-out, stroke-opacity 0.3s ease-in;
}
3 changes: 3 additions & 0 deletions omf/static/geoJsonMap/v3/lib/leaflet.markercluster.js

Large diffs are not rendered by default.

39 changes: 33 additions & 6 deletions omf/static/geoJsonMap/v3/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function main() {
/* Setup layers */
/****************/

const maxZoom = 30;
const maxZoom = 32;
var esri_satellite_layer = L.esri.basemapLayer('Imagery', {
maxZoom: maxZoom
});
Expand All @@ -67,23 +67,23 @@ function main() {
};
const overlayMaps = {
'Nodes': LeafletLayer.nodeLayers,
'Child Nodes': LeafletLayer.childNodeLayers,
'Lines': LeafletLayer.lineLayers,
'Parent-Child Lines': LeafletLayer.parentChildLineLayers,
}
const map = L.map('map', {
LeafletLayer.map = L.map('map', {
center: LeafletLayer.nodeLayers.getBounds().getCenter(),
// - This zoom level sensibly displays all circuits to start, even the ones with weird one-off players that skew where the center is
zoom: 14,
// - Provide the layers that the map should start with
layers: [esri_satellite_layer, LeafletLayer.nodeLayers, LeafletLayer.lineLayers],
layers: [esri_satellite_layer, LeafletLayer.nodeLayers, LeafletLayer.lineLayers, LeafletLayer.parentChildLineLayers],
// - Better performance for large datasets
renderer: L.canvas()
});
LeafletLayer.map = map;
LeafletLayer.map.fitBounds(LeafletLayer.nodeLayers.getBounds());
addZoomToFitButon();
L.control.layers(baseMaps, overlayMaps, { position: 'topleft', collapsed: false }).addTo(map);
addClusterButton();
LeafletLayer.control = L.control.layers(baseMaps, overlayMaps, { position: 'topleft', collapsed: false });
LeafletLayer.control.addTo(LeafletLayer.map);
// - Disable the following annoying default Leaflet keyboard shortcuts:
// - TODO: do a better job and stop the event(s) from propagating in text inputs instead
document.getElementById('map').onkeydown = function(e) {
Expand Down Expand Up @@ -334,6 +334,33 @@ function addZoomToFitButon() {
leafletHookDiv.appendChild(div);
}

/**
* @returns {undefined}
*/
function addClusterButton() {
const leafletHookDiv = document.querySelector('div.leaflet-top.leaflet-left');
const div = document.createElement('div');
div.classList.add('leaflet-control', 'leaflet-touch', 'leaflet-control-layers', 'leaflet-bar');
const button = document.createElement('button');
button.classList.add('leaflet-custom-control-button');
button.textContent = 'Toggle Node Grouping';
button.addEventListener('click', function() {
LeafletLayer.map.removeLayer(LeafletLayer.nodeLayers);
LeafletLayer.control.removeLayer(LeafletLayer.nodeLayers);
if (LeafletLayer.nodeLayers instanceof L.MarkerClusterGroup) {
LeafletLayer.nodeLayers = L.featureGroup(LeafletLayer.nodeLayers.getLayers());
} else {
const nodeLayers = LeafletLayer.nodeLayers.getLayers();
LeafletLayer.nodeLayers = L.markerClusterGroup();
nodeLayers.forEach(l => LeafletLayer.nodeLayers.addLayer(l));
}
LeafletLayer.control.addOverlay(LeafletLayer.nodeLayers, 'Nodes');
LeafletLayer.map.addLayer(LeafletLayer.nodeLayers);
});
div.appendChild(button);
leafletHookDiv.appendChild(div);
}

(function loadInterface() {
const modalInsert = document.createElement('div');
modalInsert.id = 'modalInsert';
Expand Down
4 changes: 4 additions & 0 deletions omf/templates/geoJson.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
<script type="text/javascript" src="/static/geoJsonMap/v3/lib/papaparse.min.js"></script>
<!-- Color scale -->
<script type="text/javascript" src="/static/geoJsonMap/v3/lib/chroma.min.js"></script>
<!-- Marker clustering -->
<link rel="stylesheet" href="/static/geoJsonMap/v3/lib/MarkerCluster.css" />
<link rel="stylesheet" href="/static/geoJsonMap/v3/lib/MarkerCluster.Default.css" />
<script type="text/javascript" src="/static/geoJsonMap/v3/lib/leaflet.markercluster.js"></script>
<!-- Local -->
<link rel="stylesheet" href="/static/geoJsonMap/v3/dropdownDiv.css">
<link rel="stylesheet" href="/static/geoJsonMap/v3/leafletLayer.css">
Expand Down

0 comments on commit 3983cc6

Please sign in to comment.