-
-
Notifications
You must be signed in to change notification settings - Fork 60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
User geolocation in Google Maps #784
Merged
JeroenDeDauw
merged 22 commits into
ProfessionalWiki:master
from
stevygee:202409-mylocation
Nov 13, 2024
Merged
Changes from 13 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
2b5b8dd
Add checkbox for user geolocation location
stevygee 05cb4fe
Move control into map, multiple map support
stevygee f66e856
Add mylocation parameter
stevygee 5a2ce9b
Draw circle for my location, replacing marker
stevygee 9aa0b26
Update my location accuracy on every update
stevygee 283bac7
Fix my location circle position update
stevygee c830a35
Fix map centering every time my location updates
stevygee 1acbedd
Use icon for my location toggle
stevygee 66efb4a
Add translation string
stevygee ae0d7e6
Add marker to user location
stevygee 61b1988
Follow user on map per default, stop following on drag
stevygee 666cb8a
Fix AJAX markers not updating on re-center
stevygee 06e974f
Add translation string
stevygee 1fac8cb
Store my location setting in localStorage, global for all maps
stevygee e2e47ef
Temp: Disabled locked location, disable zoom into location
stevygee d1f7b91
Center on location on button press
stevygee 766ff52
Store follow my location option per map, add mylocationfollow parameter
stevygee 3734f20
Cleanup
stevygee ff79662
Add my location zoom parameter
stevygee bd567d9
Add to existing module
stevygee 2b58504
Add to existing module
stevygee 6bc5a19
Add translation string
stevygee File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
// Control for toggling the user location function | ||
function MyLocationControl( map ) { | ||
var controlDiv = document.createElement('div'); | ||
controlDiv.style.padding = '10px 10px 0px 10px'; | ||
controlDiv.index = 1; | ||
|
||
var controlUI = document.createElement('div'); | ||
controlUI.style.padding = '6px 6px'; | ||
controlUI.style.backgroundColor = 'white'; | ||
controlUI.style.borderStyle = 'solid'; | ||
controlUI.style.borderColor = 'rgba(0, 0, 0, 0.14902)'; | ||
controlUI.style.borderWidth = '1px'; | ||
controlUI.style.borderRadius = '2px'; | ||
controlUI.style.cursor = 'pointer'; | ||
controlUI.style.textAlign = 'center'; | ||
controlUI.style.boxShadow = 'rgba(0, 0, 0, 0.298039) 0px 1px 4px -1px'; | ||
controlUI.style.backgroundClip = 'padding-box'; | ||
controlUI.title = mw.msg('maps-mylocation-button-tooltip'); | ||
controlDiv.appendChild(controlUI); | ||
|
||
var controlText = document.createElement('div'); | ||
controlText.style.backgroundPosition = '0 0'; | ||
controlText.style.backgroundImage = 'url(' + mw.config.get( 'egMapsScriptPath' ) + '/resources/GoogleMaps/img/mylocation-sprite-2x.png)'; | ||
controlText.style.backgroundSize = '180px 18px'; | ||
controlText.style.display = 'block'; | ||
controlText.style.height = '18px'; | ||
controlText.style.left = '6px'; | ||
controlText.style.margin = '0'; | ||
controlText.style.padding = '0'; | ||
controlText.style.width = '18px'; | ||
controlUI.appendChild(controlText); | ||
|
||
// Handle toggle button click | ||
google.maps.event.addDomListener( controlUI, 'click', function() { | ||
let mapDiv = $( map.getDiv() ); | ||
|
||
if ( mapDiv.data( 'followMyLocation' ) != null ) { | ||
mapDiv.removeData( 'followMyLocation' ); | ||
controlText.style.backgroundPosition = '0 0'; | ||
deactivateMyLocation( map ); | ||
} else { | ||
mapDiv.data( 'followMyLocation', 'locked' ); | ||
controlText.style.backgroundPosition = '-144px 0'; | ||
activateMyLocation( map ); | ||
} | ||
} ); | ||
|
||
// Handle dragged map | ||
google.maps.event.addDomListener( map, 'dragend', function() { | ||
let mapDiv = $( map.getDiv() ); | ||
|
||
// Continue tracking location, without centering on user | ||
if ( mapDiv.data( 'followMyLocation' ) != null ) { | ||
mapDiv.data( 'followMyLocation', 'passive' ); | ||
} | ||
} ); | ||
|
||
return controlDiv; | ||
} | ||
window.MyLocationControl = MyLocationControl; | ||
|
||
function handleLocationError( browserHasGeolocation, pos ) { | ||
console.log( browserHasGeolocation ? | ||
'Error: The Geolocation service failed.' : | ||
'Error: Your browser doesn\'t support geolocation.' ); | ||
} | ||
|
||
function drawMyLocation( position, map ) { | ||
let pos = { | ||
lat: position.coords.latitude, | ||
lng: position.coords.longitude | ||
}; | ||
let radius = position.coords.accuracy * 0.5; | ||
|
||
let mapDiv = $( map.getDiv() ); | ||
|
||
if ( typeof mapDiv.data( 'myLocationMarker' ) === 'undefined' ) { | ||
// Add a circle to visualize geolocation accuracy | ||
let myLocationCircle = new google.maps.Circle( { | ||
strokeWeight: 0, | ||
fillColor: "#5383EC", | ||
fillOpacity: 0.2, | ||
map, | ||
center: pos, | ||
radius: radius, | ||
} ); | ||
|
||
// Add a marker at the user's location | ||
const svgMarker = { | ||
path: "M 11, 11 m 10, 0 a 10,10 0 1,0 -20,0 a 10,10 0 1,0 20,0", | ||
fillColor: "#5383EC", | ||
fillOpacity: 1, | ||
strokeWeight: 2, | ||
strokeColor: "white", | ||
anchor: new google.maps.Point( 11, 11 ), | ||
scale: 0.75, | ||
}; | ||
|
||
let myLocationMarker = new google.maps.Marker( { | ||
position: pos, | ||
icon: svgMarker, | ||
map: map, | ||
} ); | ||
|
||
// Zoom into user's location | ||
map.setZoom( 16 ); | ||
|
||
// Store for later access | ||
mapDiv.data( 'myLocationMarker', myLocationMarker ); | ||
mapDiv.data( 'myLocationCircle', myLocationCircle ); | ||
} else { | ||
// Update position and radius | ||
mapDiv.data( 'myLocationMarker' ).setPosition( pos ); | ||
mapDiv.data( 'myLocationCircle' ).setCenter( pos ); | ||
mapDiv.data( 'myLocationCircle' ).setRadius( radius ); | ||
} | ||
|
||
if ( mapDiv.data( 'followMyLocation' ) === 'locked' ) { | ||
// Center the map on the user's location | ||
map.setCenter( pos ); | ||
} | ||
} | ||
|
||
function activateMyLocation( map ) { | ||
mapDiv = $( map.getDiv() ); | ||
|
||
// Check if geolocation is supported | ||
if ( navigator.geolocation ) { | ||
let myLocationWatchId = navigator.geolocation.watchPosition( | ||
function( position ) { | ||
drawMyLocation( position, map ); | ||
}, | ||
// Error handling | ||
function() { | ||
handleLocationError( true, map.getCenter() ); | ||
}, | ||
// Geolocation options | ||
{ | ||
enableHighAccuracy: true, | ||
timeout: 5000, | ||
maximumAge: 0, | ||
} | ||
); | ||
mapDiv.data( 'myLocationWatchId', myLocationWatchId ); | ||
} else { | ||
// Browser doesn't support geolocation | ||
handleLocationError( false, map.getCenter() ); | ||
} | ||
} | ||
|
||
function deactivateMyLocation( map ) { | ||
mapDiv = $( map.getDiv() ); | ||
|
||
// Check if geolocation is supported | ||
if ( navigator.geolocation ) { | ||
// Stop tracking location | ||
navigator.geolocation.clearWatch( mapDiv.data( 'myLocationWatchId' ) ); | ||
mapDiv.removeData( 'myLocationWatchId' ); | ||
} | ||
|
||
// Remove marker from the map | ||
if ( typeof mapDiv.data( 'myLocationMarker' ) !== 'undefined' ) { | ||
mapDiv.data( 'myLocationMarker' ).setMap( null ); | ||
mapDiv.removeData( 'myLocationMarker' ); | ||
} | ||
|
||
// Remove circle from the map | ||
if ( typeof mapDiv.data( 'myLocationCircle' ) !== 'undefined' ) { | ||
mapDiv.data( 'myLocationCircle' ).setMap( null ); | ||
mapDiv.removeData( 'myLocationCircle' ); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you always load the new js file anyway, you could put it in one of the existing modules.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I'm not very familiar how script loading works in MediaWiki, but I've added it to the
ext.maps.googlemaps3
module now.