diff options
Diffstat (limited to 'index.html')
-rwxr-xr-x | index.html | 299 |
1 files changed, 133 insertions, 166 deletions
@@ -1,179 +1,146 @@ <!DOCTYPE html> <html lang="en"> <head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <title>Calimoto GPX to Google Maps - Flexible Start/End</title> - <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/> - <style> - body { - font-family: Arial, sans-serif; - margin: 1em; - padding: 0; - box-sizing: border-box; - } - - label, select, input[type="file"] { - margin-bottom: 1em; - display: block; - width: 100%; - font-size: 1rem; - padding: 10px; - box-sizing: border-box; - } - - select, input[type="file"] { - font-size: 1.1rem; - } - - #result { - margin-top: 1em; - } - - #map { - width: 100%; - height: 40vh; - margin-top: 1em; - border: 1px solid #ccc; - } - - a { - word-break: break-word; - color: #007BFF; - text-decoration: none; - } - - a:hover { - text-decoration: underline; - } - - @media screen and (max-width: 768px) { - #map { - height: 30vh; - } - - h1 { - font-size: 1.5rem; - text-align: center; - } - - .container { - padding: 1em; - } - } - - @media screen and (max-width: 480px) { - label, select, input[type="file"] { - font-size: 1rem; - } - - #map { - height: 35vh; - } - } - </style> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Calimoto GPX to Google Maps - Smart Routing</title> + <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/> + <style> + body { + font-family: Arial, sans-serif; + margin: 1em; + } + label, select, input[type="file"] { + margin-bottom: 1em; + display: block; + width: 100%; + font-size: 1rem; + padding: 10px; + } + #map { + width: 100%; + height: 40vh; + margin-top: 1em; + border: 1px solid #ccc; + } + a { + word-break: break-word; + color: #007BFF; + text-decoration: none; + } + a:hover { + text-decoration: underline; + } + </style> </head> <body> - <h1>Calimoto GPX to Google Maps Directions</h1> - <div class="container"> - <label for="mode">Start/end point:</label> - <select id="mode"> - <option value="office">Use predefined start/end (Office)</option> - <option value="original">Use original GPX start/end</option> - </select> - - <input type="file" id="gpxfile" accept=".gpx"/> - <div id="result"></div> - <div id="map"></div> + <label for="gpxfile">Upload GPX File:</label> + <input type="file" id="gpxfile" accept=".gpx"/> + <div id="result"></div> + <div id="map"></div> </div> - <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> <script> - let map = L.map('map').setView([46.962153, 7.446944], 13); - L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { - attribution: '© OpenStreetMap contributors' - }).addTo(map); - let routeLine; // to reuse and update the route line - document.getElementById('gpxfile').addEventListener('change', function (event) { - // Predefined start/end point (Office) - const fixedStartLat = 46.962153; - const fixedStartLon = 7.446944; - const fixedStart = `${fixedStartLat},${fixedStartLon}`; - - const file = event.target.files[0]; - if (!file) return; - - const mode = document.getElementById('mode').value; - - const reader = new FileReader(); - reader.onload = function (e) { - const parser = new DOMParser(); - const xmlDoc = parser.parseFromString(e.target.result, "application/xml"); - - const routePoints = xmlDoc.getElementsByTagName('rtept'); - if (routePoints.length < 3) { - document.getElementById('result').innerHTML = "Not enough <rtept> points."; - return; - } - - const coords = []; - let startCoord = ""; - let endCoord = ""; - - for (let i = 0; i < routePoints.length; i++) { - const lat = routePoints[i].getAttribute('lat'); - const lon = routePoints[i].getAttribute('lon'); - coords.push(lat + "," + lon); - } - - if (mode === "original") { - startCoord = routePoints[0].getAttribute('lat') + "," + routePoints[0].getAttribute('lon'); - endCoord = routePoints[routePoints.length - 1].getAttribute('lat') + "," + routePoints[routePoints.length - 1].getAttribute('lon'); - } else if (mode === "office") { - startCoord = fixedStart; - endCoord = fixedStart; - } - - const MAX_WAYPOINTS = 23; - let selectedCoords = []; - const availableSlots = MAX_WAYPOINTS - 2; - - if (coords.length <= availableSlots) { - selectedCoords = coords; - } else { - const interval = coords.length / availableSlots; - for (let i = 1; i < availableSlots - 1; i++) { - const index = Math.round(i * interval); - if (index >= coords.length) break; - selectedCoords.push(coords[index]); - } - } - - const fullCoords = [startCoord, ...selectedCoords, endCoord]; - const baseUrl = "https://www.google.com/maps/dir/"; - const url = baseUrl + fullCoords.join('/'); - - document.getElementById('result').innerHTML = ` - <p><strong>Directions Link:</strong></p> - <p><a href="${url}" target="_blank">${url}</a></p> - `; - - // Draw route preview on map - const latLngs = fullCoords.map(pt => { - const [lat, lon] = pt.split(',').map(Number); - return [lat, lon]; - }); - - if (routeLine) map.removeLayer(routeLine); - routeLine = L.polyline(latLngs, {color: 'blue', weight: 4}).addTo(map); - map.fitBounds(routeLine.getBounds()); - }; + let map = L.map('map').setView([46.962153, 7.446944], 13); + L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + attribution: '© OpenStreetMap contributors' + }).addTo(map); + let routeLine; + + function getDistance(lat1, lon1, lat2, lon2) { + const toRad = deg => deg * Math.PI / 180; + const R = 6371e3; // meters + const dLat = toRad(lat2 - lat1); + const dLon = toRad(lon2 - lon1); + const a = Math.sin(dLat/2)**2 + + Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * + Math.sin(dLon/2)**2; + const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + return R * c; + } + + function downsampleWaypoints(coords, max = 21) { + if (coords.length <= max) return coords; + const interval = coords.length / max; + const result = []; + for (let i = 0; i < max; i++) { + const index = Math.round(i * interval); + if (index < coords.length) result.push(coords[index]); + } + return result; + } + + document.getElementById('gpxfile').addEventListener('change', function (event) { + const file = event.target.files[0]; + if (!file) return; + + const reader = new FileReader(); + reader.onload = function (e) { + const parser = new DOMParser(); + const xmlDoc = parser.parseFromString(e.target.result, "application/xml"); + + const routePoints = xmlDoc.getElementsByTagName('rtept'); + if (routePoints.length < 3) { + document.getElementById('result').innerHTML = "Not enough <rtept> points."; + return; + } + + const coords = []; + for (let i = 0; i < routePoints.length; i++) { + const lat = routePoints[i].getAttribute('lat'); + const lon = routePoints[i].getAttribute('lon'); + coords.push(lat + "," + lon); + } + + const endCoord = coords[coords.length - 1]; + + navigator.geolocation.getCurrentPosition(function (position) { + const userLat = position.coords.latitude; + const userLon = position.coords.longitude; + let closestIndex = 0; + let minDist = Infinity; + + for (let i = 0; i < coords.length; i++) { + const [lat, lon] = coords[i].split(',').map(Number); + const dist = getDistance(userLat, userLon, lat, lon); + if (dist < minDist) { + minDist = dist; + closestIndex = i; + } + } - reader.readAsText(file); - }); + const remainingCoords = coords.slice(closestIndex); + const selectedCoords = downsampleWaypoints(remainingCoords); + + const startCoord = "Current+Location"; + const leafletStartCoord = `${userLat},${userLon}`; + const fullCoords = [startCoord, ...selectedCoords, endCoord]; + + const baseUrl = "https://www.google.com/maps/dir/"; + const url = baseUrl + fullCoords.join('/'); + + document.getElementById('result').innerHTML = ` + <p><strong>Directions Link:</strong></p> + <p><a href="${url}" target="_blank">${url}</a></p> + `; + + // Draw preview + const latLngs = [leafletStartCoord, ...selectedCoords, endCoord].map(pt => { + const [lat, lon] = pt.split(',').map(Number); + return [lat, lon]; + }); + + if (routeLine) map.removeLayer(routeLine); + routeLine = L.polyline(latLngs, {color: 'blue', weight: 4}).addTo(map); + map.fitBounds(routeLine.getBounds()); + }, function (error) { + document.getElementById('result').innerHTML = "Error fetching location: " + error.message; + }); + }; + reader.readAsText(file); + }); </script> - </body> -</html> +</html>
\ No newline at end of file |