domoritz / leaflet-locatecontrol

A leaflet control to geolocate the user.
https://domoritz.github.io/leaflet-locatecontrol/demo/
MIT License
812 stars 264 forks source link

Not finding location in Chrome & Firefox for Mobile #334

Open walkbmc opened 1 year ago

walkbmc commented 1 year ago

Locator is not finding a location on either Chrome or Firefox for mobile, just spins and spins, no errors or anything

nitinkg7 commented 1 year ago

I am also facing this issue in ios webview

Mary-Tyler-Moore commented 1 year ago

I'm facing this same issue. The demo website ( https://domoritz.github.io/leaflet-locatecontrol/demo/ ) works on Android when using Chrome, and work on iOS when using Safari, but does not work on iOS when using Chrome.

I've noticed that when it works two messages are displayed: 1: "domoritz.github.io" would like to use your current location. 2: "domoritz.github.io" Would like to Access Motion and Orientation

iOS_Safari_1

iOS_Safari_2

And when it doesn't work, when using the Chrome browser on an iOS device, only one message is displayed: 1: "domoritz.github.io" Would like to Access Motion and Orientation

iOS_Chrome_1

iOS_Chrome_2

tchercheuse commented 1 year ago

Same issue here. Have you figured this out ?

Mary-Tyler-Moore commented 1 year ago

@tchercheuse - I decided to create a custom Leaflet control that allows users to locate their position on the map using the browser's geolocation capabilities.

` L.Control.UserLocation = L.Control.extend({ options: { position: 'bottomright', // Changed position to 'bottomright' title: 'Locate user' },

onAdd: function (map) {
    const controlDiv = L.DomUtil.create('div', 'leaflet-bar leaflet-control leaflet-control-userlocation');
    L.DomEvent
        .addListener(controlDiv, 'click', L.DomEvent.stopPropagation)
        .addListener(controlDiv, 'click', L.DomEvent.preventDefault)
        .addListener(controlDiv, 'click', () => this._locateUser(map));

    const controlUI = L.DomUtil.create('a', 'leaflet-control-userlocation-button', controlDiv);
    controlUI.title = this.options.title;
    controlUI.href = '#';
    controlUI.innerHTML = '📍';  // You can replace this with any icon or text for the control

    return controlDiv;
},

_locateUser: function (map) {
    if (!this._userMarker) {
        // Use circleMarker for a different style
        this._userMarker = L.circleMarker(map.getCenter(), {
            radius: 10,  // Adjust the size of the circle marker
            color: '#520066',  // Color of the circle marker
            fillColor: '#cb65ff',
            fillOpacity: 1
        }).addTo(map);
    }

    if (navigator.geolocation) {
        navigator.geolocation.watchPosition(
            (position) => {
                const latlng = new L.LatLng(position.coords.latitude, position.coords.longitude);
                this._userMarker.setLatLng(latlng);
                map.panTo(latlng); // Comment out to update the location without re-centering map
            },
            (error) => {
                console.error("Error retrieving user location:", error);
            },
            {
                enableHighAccuracy: true
            }
        );
    } else {
        console.error("Geolocation is not supported by this browser.");
    }
}

});

map.addControl(new L.Control.UserLocation()); `

Here's how it works:

L.Control.UserLocation = L.Control.extend({ ... });: This code defines a new Leaflet control called UserLocation by extending the L.Control class. It means that this custom control will inherit properties and methods from the L.Control class, making it function like any other built-in control in Leaflet.

The options object contains configuration properties for the control. In this case, it defines the position of the control on the map (bottom right) and the title displayed as a tooltip on the control button. The onAdd method is executed when the control is added to the map using map.addControl(new L.Control.UserLocation());. It creates the necessary HTML elements for the control and attaches event listeners to handle clicks.

The addListener method from L.DomEvent is used to prevent the default behavior of clicks on the control, which avoids any unintended side effects.

_locateUser is a private method that handles the geolocation functionality. When the user clicks the control button, it triggers the _locateUser function.

_userMarker is a private variable that represents the user's location marker on the map. It is a circle marker with a specified color and size.

navigator.geolocation.watchPosition is the heart of the geolocation functionality. It uses the browser's built-in geolocation API to continuously watch the user's position and update the marker accordingly. The watchPosition method takes three arguments:

The first argument is a success callback function that will be called with the user's updated position.

The second argument is an error callback function that will be called if there is an error retrieving the user's location.

The third argument is an options object, where you can enable high accuracy to get more precise results from the geolocation API.

Inside the success callback function, the user's latitude and longitude are extracted from the geolocation API's position.coords, and a new L.LatLng object is created from them. Then, the _userMarker's position is updated with the new coordinates, and the map is panned to center on the user's updated location.

If geolocation is not supported by the user's browser, an error message is logged to the console.

The custom control is added to the map using map.addControl(new L.Control.UserLocation());.

tchercheuse commented 1 year ago

@tchercheuse - I decided to create a custom Leaflet control that allows users to locate their position on the map using the browser's geolocation capabilities.

Thanks, we'll test that after holidays ;)