-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgeolocation-control.js
128 lines (108 loc) · 4.76 KB
/
geolocation-control.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
class GeolocationManager {
constructor(map) {
this.map = map;
this.setupGeolocation();
this.locationLabelSet = false;
this.isTracking = false;
}
setupGeolocation() {
// Add geolocate control with bearing tracking
this.geolocate = new mapboxgl.GeolocateControl({
positionOptions: {
enableHighAccuracy: true
},
trackUserLocation: false,
showUserHeading: true,
fitBoundsOptions: {
zoom: 18
}
});
this.map.addControl(this.geolocate);
// Track when tracking starts/stops
this.geolocate.on('trackuserlocationstart', () => {
this.isTracking = true;
$(window).on('deviceorientationabsolute', this.handleOrientation);
});
this.geolocate.on('trackuserlocationend', () => {
this.isTracking = false;
$(window).off('deviceorientationabsolute', this.handleOrientation);
});
// Handle successful geolocation
this.geolocate.on('geolocate', async (event) => {
this.lastPosition = event;
// Set initial map position
this.map.easeTo({
center: [event.coords.longitude, event.coords.latitude],
zoom: 18,
pitch: 0,
bearing: 0, // North
duration: 1000 // 1 second animation
});
if (!this.locationLabelSet) {
try {
const response = await fetch(
`https://api.mapbox.com/geocoding/v5/mapbox.places/${event.coords.longitude},${event.coords.latitude}.json?access_token=${mapboxgl.accessToken}&types=poi,address,neighborhood,locality,place&limit=1`
);
const data = await response.json();
const feature = data.features[0];
let addressText = 'Unknown location';
if (feature) {
const parts = [];
if (feature.properties?.name) {
parts.push(feature.properties.name);
}
if (feature.context) {
const relevantTypes = ['neighborhood', 'locality', 'place', 'district'];
feature.context
.filter(ctx => relevantTypes.includes(ctx.id.split('.')[0]))
.forEach(ctx => parts.push(ctx.text));
}
addressText = parts.join(', ');
}
// Update the geolocate button using jQuery
const $geolocateButton = $('.mapboxgl-ctrl-geolocate');
if ($geolocateButton.length) {
const $buttonParent = $geolocateButton.parent();
// Style the container
$buttonParent.css({
minWidth: 'auto',
width: 'auto'
});
// Style the button
$geolocateButton.css({
width: 'auto',
minWidth: '30px',
whiteSpace: 'nowrap',
padding: '6px 10px'
});
// Remove any existing location text
$geolocateButton.find('span:not(.mapboxgl-ctrl-icon)').remove();
// Add new location text
$('<span>', {
text: `My location: ${addressText}`,
css: { marginLeft: '5px' }
}).appendTo($geolocateButton);
this.locationLabelSet = true;
}
} catch (error) {
console.error('Error reverse geocoding:', error);
}
}
if (this.isTracking && event.coords?.heading) {
this.map.easeTo({
bearing: event.coords.heading,
duration: 300
});
}
});
}
handleOrientation = (event) => {
if (event.alpha && this.isTracking) {
const bearing = 360 - event.alpha;
this.map.easeTo({
bearing: bearing,
duration: 100
});
}
}
}