Define min/max bounds for bbox updates to avoid constant updates while locate control is active

pull/271/head
Candid Dauth 2024-04-26 12:25:12 +02:00
rodzic 1ae85c2232
commit 4152c667bf
1 zmienionych plików z 35 dodań i 10 usunięć

Wyświetl plik

@ -1,7 +1,7 @@
import type Client from "facilmap-client";
import type { ClientEvents } from "facilmap-client";
import type { EventHandler } from "facilmap-types";
import { Handler, LatLng, LatLngBounds, Map } from "leaflet";
import { Bounds, Handler, LatLng, LatLngBounds, Map } from "leaflet";
import { leafletToFmBbox } from "./utils/leaflet";
const flyToBkp = Map.prototype.flyTo;
@ -11,9 +11,23 @@ Map.prototype.flyTo = function(...args) {
return flyToBkp.apply(this, args);
};
function extendBounds(bounds: Bounds, pixels: number): Bounds {
return new Bounds(
[bounds.getTopLeft().x - pixels, bounds.getTopLeft().y - pixels],
[bounds.getBottomRight().x + pixels, bounds.getBottomRight().y + pixels]
);
}
export default class BboxHandler extends Handler {
margin = 50;
/**
* The min and max values how much wider the map pixel bounds should be used than what they actually are.
* By default, the max value is used. If the map is panned and the last bounds are still within the range
* of the min value, no update is triggered. This avoids an update every second when the locate control
* adjusts the map position very slightly.
*/
margin = [50, 400];
lastBounds: { bounds: Bounds; zoom: number } | undefined = undefined;
client: Client;
@ -26,17 +40,23 @@ export default class BboxHandler extends Handler {
if (!this._map._loaded && (center == null || zoom == null))
return;
const pixelBounds = this._map.getPixelBounds(center, zoom);
pixelBounds.min!.x -= this.margin;
pixelBounds.min!.y -= this.margin;
pixelBounds.max!.x += this.margin;
pixelBounds.max!.y += this.margin;
const resolvedZoom = zoom ?? this._map.getZoom();
const pixelBounds = this._map.getPixelBounds(center, resolvedZoom);
if (this.lastBounds && this.lastBounds.zoom === resolvedZoom) {
const minBounds = extendBounds(pixelBounds, this.margin[0]);
if (this.lastBounds.bounds.contains(minBounds)) {
return;
}
}
const maxBounds = extendBounds(pixelBounds, this.margin[1]);
const bounds = new LatLngBounds(
this._map.unproject(pixelBounds.getBottomLeft(), zoom),
this._map.unproject(pixelBounds.getTopRight(), zoom)
this._map.unproject(maxBounds.getBottomLeft(), resolvedZoom),
this._map.unproject(maxBounds.getTopRight(), resolvedZoom)
);
void this.client.updateBbox(leafletToFmBbox(bounds ?? this._map.getBounds(), zoom ?? this._map.getZoom()));
void this.client.updateBbox(leafletToFmBbox(bounds, resolvedZoom));
this.lastBounds = { bounds: maxBounds, zoom: resolvedZoom };
}
shouldUpdateBbox(): boolean {
@ -72,6 +92,10 @@ export default class BboxHandler extends Handler {
this._map.on("viewreset", this.handleViewReset);
this._map.on("fmFlyTo", this.handleFlyTo);
this.client.on("emitResolve", this.handleEmitResolve);
if (this.shouldUpdateBbox()) {
this.updateBbox();
}
}
removeHooks(): void {
@ -79,5 +103,6 @@ export default class BboxHandler extends Handler {
this._map.off("viewreset", this.handleViewReset);
this._map.off("fmFlyTo", this.handleFlyTo);
this.client.removeListener("emitResolve", this.handleEmitResolve);
this.lastBounds = undefined;
}
}