Fix zoom feature on tracking map

Job ID: 37237845

Budget: $250 – $750 USD

We have a map showing athletes on a course, and our previous developer included a feature whereby the map zooms to the participants. However, it is not working anymore and the current developers haven't had capacity to look at it as they are busy with other parts of the app. We need to find the bug and fix it.

The full code is in github, but below is the relevant section.

Note: If you do not have experience with maps, please do not respond to this.

/*
If the athletes move and the user has not yet interacted with the map, pan the map so all athletes still show.
If the athletes move and the user has interacted with the map within the last 5 minutes, do nothing.
It the athletes move, and the user has not interacted in the last 5 minutes then pan to show all athletes in the race.
It the athletes move, and the user has not interacted in the last 5 minutes, and the user has selected favourites - then pan to show the selected favourites.
*/
fitPositionsBounds() {
const {
status,
athletes,
positions,
checkpoints,
isMoving,
simulateMassStart,
} = this.props;
const map = this.context.map;
const bounds = this.featureGroup.getBounds();
const isFinished = Object.keys(athletes).filter(
(id) => athletes[id].isFinished
).length
? true
: false;
const padding = window.innerWidth < 500 ? [50, 50] : [100, 100]; // Don't zoom too tight
const maxZoom = 14;
const options = { padding, maxZoom };

if (bounds.isValid() && simulateMassStart !== this.simulateMassStart) {
this.simulateMassStart = simulateMassStart;
map.fitBounds(bounds, options);
}

if (
status !== "after" &&
!isFinished &&
!this.bounds &&
!isMoving &&
checkpoints &&
checkpoints.length
) {
const startBounds = L.latLngBounds();

startBounds.extend(checkpoints[0]);
startBounds.extend(checkpoints[1]);

// flyToBounds only works if map has an initial view
if (map.getZoom() === undefined) {
map.fitBounds(startBounds, options);
} else {
map.flyToBounds(startBounds, {
duration: 4,
padding,
maxZoom,
});
}
}

// First bounds set - TODO: Don't set if map is zoomed to start
if (status !== "after" && bounds.isValid() && isMoving) {
if (!this.bounds) {
map.whenReady(() => {
if (map.getBounds().isValid()) {
map.flyToBounds(bounds, options);
} else {
map.fitBounds(bounds, options);
}
});
// Store bounds so we now that the map is zoomed once
this.bounds = bounds;
} else {
if (!this.lastInteraction) {
// User has not been interacting with map
map.flyToBounds(bounds, options);
} else {
// User has been interacting with the map
const secondsSinceLastInteraction =
(Date.now() - this.lastInteraction) / 1000;

// Fly to bounds if user is inactive
if (secondsSinceLastInteraction > MAP_INACTIVITY_TIME) {
const selectedAthletes = Object.keys(athletes).filter(
(id) => positions[id] && athletes[id].isSelected
);

if (selectedAthletes.length) {
const mapBounds = map.getBounds();
const selectedAthletesBounds = selectedAthletes.reduce(
(latLngBounds, id) => latLngBounds.extend(positions[id]),
L.latLngBounds()
);
const zoom = map.getZoom();

if (!mapBounds.contains(selectedAthletesBounds)) {
const onFlyEnd = () => {
map.off("moveend", onFlyEnd);

// Second try: Zoom to athlete bounds if needed
if (!mapBounds.contains(selectedAthletesBounds)) {
map.flyToBounds(selectedAthletesBounds, options);
}
};

if (zoom < 12) {
// First try: Fly to center of selected athletes, keep zoom
map.on("moveend", onFlyEnd);
map.flyTo(selectedAthletesBounds.getCenter());
} else {
map.flyToBounds(selectedAthletesBounds, options);
}
}
} else {
map.flyToBounds(bounds, options); // Fit to all athletes
}
}
}
}
}
}
Related categories: Cartography & Maps MySQL GPS