Implemented trackResize for L.Popup (#9605)

Signed-off-by: Iván Sánchez Ortega <ivan@sanchezortega.es>
This commit is contained in:
Iván Sánchez Ortega
2025-03-01 12:55:08 +01:00
committed by GitHub
parent 7d6bb49a43
commit 45c795a515
2 changed files with 72 additions and 8 deletions

View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Leaflet debug page - Popup Offset</title>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0" />
<link rel="stylesheet" href="../../dist/leaflet.css" />
<link rel="stylesheet" href="../css/screen.css" />
<script type="importmap">
{
"imports": {
"leaflet": "../../dist/leaflet-src.esm.js"
}
}
</script>
</head>
<body>
<div id="map"></div>
<script type="module">
import {TileLayer, Map, Marker} from 'leaflet';
const osm = new TileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {maxZoom: 18});
const map = new Map('map').setView([50.5, 30.51], 15).addLayer(osm);
let marker = new Marker(map.getCenter())
.addTo(map);
marker.bindPopup("foobar", {maxWidth: 600, trackResize: true}); // NOTE: change to true!!
setTimeout(()=>{
marker.getPopup().setContent(`Lorem ipsum sit amet.
<img id="image" src="https://cataas.com/cat?height=${480 + Math.random() * 80}&v=${Math.random()}" />`);
}, 2500);
marker.on('click',()=>{
marker.getPopup().setContent(`Lorem ipsum sit amet.
<img id="image" src="https://cataas.com/cat?height=${480 + Math.random() * 80}&v=${Math.random()}" />`);
})
marker.openPopup();
</script>
</body>
</html>

View File

@ -117,7 +117,12 @@ export const Popup = DivOverlay.extend({
// @option className: String = '' // @option className: String = ''
// A custom CSS class name to assign to the popup. // A custom CSS class name to assign to the popup.
className: '' className: '',
// @option trackResize: Boolean = true
// Whether the popup shall react to changes in the size of its contents
// (e.g. when an image inside the popup loads) and reposition itself.
trackResize: true,
}, },
// @namespace Popup // @namespace Popup
@ -220,6 +225,21 @@ export const Popup = DivOverlay.extend({
this.close(); this.close();
}, this); }, this);
} }
if (this.options.trackResize) {
this._resizeObserver = new ResizeObserver(((entries) => {
if (!this._map) { return; }
this._containerWidth = entries[0]?.contentRect?.width;
this._containerHeight = entries[0]?.contentRect?.height;
this._updateLayout();
this._updatePosition();
this._adjustPan();
}));
this._resizeObserver.observe(this._contentNode);
}
}, },
_updateLayout() { _updateLayout() {
@ -229,16 +249,13 @@ export const Popup = DivOverlay.extend({
style.width = ''; style.width = '';
style.whiteSpace = 'nowrap'; style.whiteSpace = 'nowrap';
let width = container.offsetWidth; style.maxWidth = `${this.options.maxWidth}px`;
width = Math.min(width, this.options.maxWidth); style.minWidth = `${this.options.minWidth}px`;
width = Math.max(width, this.options.minWidth);
style.width = `${width + 1}px`;
style.whiteSpace = ''; style.whiteSpace = '';
style.height = ''; style.height = '';
const height = container.offsetHeight, const height = this._containerHeight ?? container.offsetHeight,
maxHeight = this.options.maxHeight, maxHeight = this.options.maxHeight,
scrolledClass = 'leaflet-popup-scrolled'; scrolledClass = 'leaflet-popup-scrolled';
@ -250,6 +267,7 @@ export const Popup = DivOverlay.extend({
} }
this._containerWidth = this._container.offsetWidth; this._containerWidth = this._container.offsetWidth;
this._containerHeight = this._container.offsetHeight;
}, },
_animateZoom(e) { _animateZoom(e) {
@ -271,7 +289,7 @@ export const Popup = DivOverlay.extend({
const map = this._map, const map = this._map,
marginBottom = parseInt(getComputedStyle(this._container).marginBottom, 10) || 0, marginBottom = parseInt(getComputedStyle(this._container).marginBottom, 10) || 0,
containerHeight = this._container.offsetHeight + marginBottom, containerHeight = this._containerHeight + marginBottom,
containerWidth = this._containerWidth, containerWidth = this._containerWidth,
layerPos = new Point(this._containerLeft, -containerHeight - this._containerBottom); layerPos = new Point(this._containerLeft, -containerHeight - this._containerBottom);