-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.js
237 lines (202 loc) · 6.62 KB
/
app.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
/*
@author: @omrqd
@date: 2024-11-11
@github: https://github.com/omrqd
*/
// Initialize map variables
let map;
let userMarker;
let deliveryMarker;
let userPosition;
let deliverySimulationInterval;
let deliveryPath; // Line between delivery and user
let distanceInfoWindow; // Info window for distance/time
// Initialize the map centered on a default position
function initMap() {
// Create map centered on a default position
const defaultPosition = { lat: 51.505, lng: -0.09 };
map = new google.maps.Map(document.getElementById('map'), {
zoom: 13,
center: defaultPosition,
});
// Create a marker for user location (initially hidden)
userMarker = new google.maps.Marker({
position: defaultPosition,
map: map,
visible: false
});
// Create a marker for delivery person (initially hidden)
deliveryMarker = new google.maps.Marker({
position: defaultPosition,
map: map,
visible: false,
icon: {
url: "http://maps.google.com/mapfiles/ms/icons/green-dot.png", // Different color for delivery marker
scaledSize: new google.maps.Size(32, 32)
}
});
// Create delivery path line (initially hidden)
deliveryPath = new google.maps.Polyline({
path: [],
geodesic: true,
strokeColor: '#4CAF50',
strokeOpacity: 1.0,
strokeWeight: 2,
map: map,
visible: false
});
// Create info window for distance/time
distanceInfoWindow = new google.maps.InfoWindow();
// Start tracking user location
trackUserLocation();
}
// Function to animate marker movement smoothly
function animateMarkerMovement(marker, startPos, endPos) {
const frames = 50; // Number of animation frames
let count = 0;
const deltaLat = (endPos.lat - startPos.lat) / frames;
const deltaLng = (endPos.lng - startPos.lng) / frames;
const animate = () => {
count++;
const lat = startPos.lat + deltaLat * count;
const lng = startPos.lng + deltaLng * count;
marker.setPosition({ lat, lng });
if (count < frames) {
requestAnimationFrame(animate);
}
};
requestAnimationFrame(animate);
}
// Function to update delivery path and info
function updateDeliveryInfo() {
const deliveryPos = deliveryMarker.getPosition();
const userPos = userMarker.getPosition();
// Update path between delivery and user
deliveryPath.setPath([
{ lat: deliveryPos.lat(), lng: deliveryPos.lng() },
{ lat: userPos.lat(), lng: userPos.lng() }
]);
deliveryPath.setVisible(true);
// Calculate distance
const distance = google.maps.geometry.spherical.computeDistanceBetween(deliveryPos, userPos);
// Estimate time (assuming average speed of 30 km/h = 8.33 m/s)
const timeInSeconds = distance / 8.33;
const minutes = Math.round(timeInSeconds / 60);
// Update info window
const content = `
Distance: ${Math.round(distance)}m<br>
Estimated arrival: ${minutes} min
`;
distanceInfoWindow.setContent(content);
distanceInfoWindow.setPosition(google.maps.geometry.spherical.interpolate(deliveryPos, userPos, 0.5));
distanceInfoWindow.open(map);
}
// Function to simulate delivery person movement
function simulateDeliveryMovement() {
// Random movement between -0.0005 and 0.0005 degrees (roughly 50 meters)
const randomLat = (Math.random() - 0.5) * 0.001;
const randomLng = (Math.random() - 0.5) * 0.001;
const currentPosition = deliveryMarker.getPosition();
const newPosition = {
lat: currentPosition.lat() + randomLat,
lng: currentPosition.lng() + randomLng
};
// Calculate heading for car rotation
const heading = google.maps.geometry.spherical.computeHeading(
currentPosition,
new google.maps.LatLng(newPosition.lat, newPosition.lng)
);
// Update car icon with rotation
deliveryMarker.setIcon({
path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
scale: 6,
fillColor: "#4CAF50",
fillOpacity: 1,
strokeWeight: 2,
rotation: heading
});
// Animate the movement
animateMarkerMovement(
deliveryMarker,
{ lat: currentPosition.lat(), lng: currentPosition.lng() },
newPosition
);
// Update delivery path and info
updateDeliveryInfo();
}
// Function to track user location
function trackUserLocation() {
if ("geolocation" in navigator) {
navigator.geolocation.watchPosition(
(position) => {
userPosition = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
// Update marker position and make visible
userMarker.setPosition(userPosition);
userMarker.setVisible(true);
// Center map on user
map.setCenter(userPosition);
map.setZoom(17); // Increased zoom level for better accuracy
// Add accuracy circle
const accuracyCircle = new google.maps.Circle({
map: map,
center: userPosition,
radius: position.coords.accuracy, // Circle radius based on accuracy in meters
fillColor: '#4285F4',
fillOpacity: 0.2,
strokeColor: '#4285F4',
strokeOpacity: 0.4,
strokeWeight: 1
});
// Initialize delivery marker near user position
if (!deliveryMarker.getVisible()) {
const initialDeliveryPosition = {
lat: userPosition.lat + 0.002,
lng: userPosition.lng + 0.002
};
deliveryMarker.setPosition(initialDeliveryPosition);
deliveryMarker.setVisible(true);
// Start delivery simulation
if (!deliverySimulationInterval) {
deliverySimulationInterval = setInterval(simulateDeliveryMovement, 2000); // Update every 2 seconds
}
}
// Update delivery path and info when user moves
if (deliveryMarker.getVisible()) {
updateDeliveryInfo();
}
},
(error) => {
console.error("Error getting location:", error);
},
{
enableHighAccuracy: true,
maximumAge: 0,
timeout: 10000, // Increased timeout for better accuracy
distanceFilter: 1 // Update position when user moves more than 1 meter
}
);
} else {
console.error("Geolocation is not supported by this browser.");
}
}
// Add CSS styles for the map container
const mapStyles = document.createElement('style');
mapStyles.textContent = `
#map {
height: 400px;
width: 100%;
}
.map-container {
padding: 20px;
}
`;
document.head.appendChild(mapStyles);
// Load Google Maps script with geometry library
const scriptElement = document.createElement('script');
scriptElement.src = `https://maps.googleapis.com/maps/api/js?key={YOUR_API_KEY}&libraries=geometry&callback=initMap`;
scriptElement.async = true;
scriptElement.defer = true;
document.head.appendChild(scriptElement);