Pause map autofit when user initiates pan/zoom (#26114)

* Pause map autofit when user initiates pan/zoom

* not a state

* a different approach
This commit is contained in:
karwosts 2025-07-09 07:32:20 -07:00 committed by GitHub
parent 5233086efb
commit e7e062a222
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 60 additions and 7 deletions

View File

@ -36,6 +36,8 @@ declare global {
}
}
const PROGRAMMITIC_FIT_DELAY = 250;
const getEntityId = (entity: string | HaMapEntity): string =>
typeof entity === "string" ? entity : entity.entity_id;
@ -113,14 +115,33 @@ export class HaMap extends ReactiveElement {
private _clickCount = 0;
private _isProgrammaticFit = false;
private _pauseAutoFit = false;
public connectedCallback(): void {
this._pauseAutoFit = false;
document.addEventListener("visibilitychange", this._handleVisibilityChange);
this._handleVisibilityChange();
super.connectedCallback();
this._loadMap();
this._attachObserver();
}
private _handleVisibilityChange = async () => {
if (!document.hidden) {
setTimeout(() => {
this._pauseAutoFit = false;
}, 500);
}
};
public disconnectedCallback(): void {
super.disconnectedCallback();
document.removeEventListener(
"visibilitychange",
this._handleVisibilityChange
);
if (this.leafletMap) {
this.leafletMap.remove();
this.leafletMap = undefined;
@ -145,7 +166,7 @@ export class HaMap extends ReactiveElement {
if (changedProps.has("_loaded") || changedProps.has("entities")) {
this._drawEntities();
autoFitRequired = true;
autoFitRequired = !this._pauseAutoFit;
} else if (this._loaded && oldHass && this.entities) {
// Check if any state has changed
for (const entity of this.entities) {
@ -154,7 +175,7 @@ export class HaMap extends ReactiveElement {
this.hass!.states[getEntityId(entity)]
) {
this._drawEntities();
autoFitRequired = true;
autoFitRequired = !this._pauseAutoFit;
break;
}
}
@ -178,7 +199,11 @@ export class HaMap extends ReactiveElement {
}
if (changedProps.has("zoom")) {
this._isProgrammaticFit = true;
this.leafletMap!.setZoom(this.zoom);
setTimeout(() => {
this._isProgrammaticFit = false;
}, PROGRAMMITIC_FIT_DELAY);
}
if (
@ -234,13 +259,30 @@ export class HaMap extends ReactiveElement {
}
this._clickCount++;
});
this.leafletMap.on("zoomstart", () => {
if (!this._isProgrammaticFit) {
this._pauseAutoFit = true;
}
});
this.leafletMap.on("movestart", () => {
if (!this._isProgrammaticFit) {
this._pauseAutoFit = true;
}
});
this._loaded = true;
} finally {
this._loading = false;
}
}
public fitMap(options?: { zoom?: number; pad?: number }): void {
public fitMap(options?: {
zoom?: number;
pad?: number;
unpause_autofit?: boolean;
}): void {
if (options?.unpause_autofit) {
this._pauseAutoFit = false;
}
if (!this.leafletMap || !this.Leaflet || !this.hass) {
return;
}
@ -250,6 +292,7 @@ export class HaMap extends ReactiveElement {
!this._mapFocusZones.length &&
!this.layers?.length
) {
this._isProgrammaticFit = true;
this.leafletMap.setView(
new this.Leaflet.LatLng(
this.hass.config.latitude,
@ -257,6 +300,9 @@ export class HaMap extends ReactiveElement {
),
options?.zoom || this.zoom
);
setTimeout(() => {
this._isProgrammaticFit = false;
}, PROGRAMMITIC_FIT_DELAY);
return;
}
@ -277,8 +323,11 @@ export class HaMap extends ReactiveElement {
});
bounds = bounds.pad(options?.pad ?? 0.5);
this._isProgrammaticFit = true;
this.leafletMap.fitBounds(bounds, { maxZoom: options?.zoom || this.zoom });
setTimeout(() => {
this._isProgrammaticFit = false;
}, PROGRAMMITIC_FIT_DELAY);
}
public fitBounds(
@ -291,7 +340,11 @@ export class HaMap extends ReactiveElement {
const bounds = this.Leaflet.latLngBounds(boundingbox).pad(
options?.pad ?? 0.5
);
this._isProgrammaticFit = true;
this.leafletMap.fitBounds(bounds, { maxZoom: options?.zoom || this.zoom });
setTimeout(() => {
this._isProgrammaticFit = false;
}, PROGRAMMITIC_FIT_DELAY);
}
private _drawLayers(prevLayers: Layer[] | undefined): void {

View File

@ -239,7 +239,7 @@ class HuiMapCard extends LitElement implements LovelaceCard {
)}
.path=${mdiImageFilterCenterFocus}
style=${isDarkMode ? "color:#ffffff" : "color:#000000"}
@click=${this._fitMap}
@click=${this._resetFocus}
tabindex="0"
></ha-icon-button>
</div>
@ -389,8 +389,8 @@ class HuiMapCard extends LitElement implements LovelaceCard {
: (root.style.paddingBottom = "100%");
}
private _fitMap() {
this._map?.fitMap();
private _resetFocus() {
this._map?.fitMap({ unpause_autofit: true });
}
private _toggleClusterMarkers() {