diff --git a/src/ui/control/geolocate_control.ts b/src/ui/control/geolocate_control.ts index 77bed43f58..ef5b434e23 100644 --- a/src/ui/control/geolocate_control.ts +++ b/src/ui/control/geolocate_control.ts @@ -303,6 +303,8 @@ export class GeolocateControl extends Evented implements IControl { } DOM.remove(this._container); + this._map.off('move', this._onMove); + this._map.off('rotate', this._onRotate); this._map.off('zoom', this._onZoom); this._map = undefined; numberOfWatches = 0; @@ -376,6 +378,11 @@ export class GeolocateControl extends Evented implements IControl { return; } + if (this.options.showAccuracyCircle) { + // this is needed by _updateCircleRadius() + this._lastKnownPosition = position; + } + if (this.options.trackUserLocation) { // keep a record of the position so that if the state is BACKGROUND and the user // clicks the button, we can move to ACTIVE_LOCK immediately without waiting for @@ -460,16 +467,30 @@ export class GeolocateControl extends Evented implements IControl { }; _updateCircleRadius() { - const bounds = this._map.getBounds(); - const southEastPoint = bounds.getSouthEast(); - const northEastPoint = bounds.getNorthEast(); - const mapHeightInMeters = southEastPoint.distanceTo(northEastPoint); - const mapHeightInPixels = this._map._container.clientHeight; - const circleDiameter = Math.ceil(2 * (this._accuracy / (mapHeightInMeters / mapHeightInPixels))); + if (!this._lastKnownPosition) return; + const center = new LngLat(this._lastKnownPosition.coords.longitude, this._lastKnownPosition.coords.latitude); + const point = this._map.project(center); + const delta_x_pixels = 10; // arbitrary small offset, in x direction because there is no map tilting in the x direction + const delta = this._map.unproject([point.x + delta_x_pixels, point.y]); + const distance = delta.distanceTo(center); + const pixelScale = distance / delta_x_pixels; + const circleDiameter = 2 * (this._accuracy / pixelScale); this._circleElement.style.width = `${circleDiameter}px`; this._circleElement.style.height = `${circleDiameter}px`; } + _onMove = () => { + if (this.options.showUserLocation && this.options.showAccuracyCircle) { + this._updateCircleRadius(); + } + }; + + _onRotate = () => { + if (this.options.showUserLocation && this.options.showAccuracyCircle) { + this._updateCircleRadius(); + } + }; + _onZoom = () => { if (this.options.showUserLocation && this.options.showAccuracyCircle) { this._updateCircleRadius(); @@ -573,6 +594,8 @@ export class GeolocateControl extends Evented implements IControl { if (this.options.trackUserLocation) this._watchState = 'OFF'; + this._map.on('move', this._onMove); + this._map.on('rotate', this._onRotate); this._map.on('zoom', this._onZoom); }