chore: migrate Google Maps to Routes API and clean up deprecated code

This commit is contained in:
2026-02-27 22:15:58 -05:00
parent 8084032f25
commit d73926cd77
5 changed files with 257 additions and 192 deletions

View File

@ -13,15 +13,15 @@ export interface Parada {
export function useDirectionsRoute() {
const estasCargando = ref<boolean>(false);
const errorRuta = ref<string | null>(null);
const { registrarRenderer, renderers } = useMapState();
const { registrarPolyline, polylines } = useMapState();
// Limpia los tramos anteriores dibujados en el mapa
const limpiarRuta = () => {
if (renderers.value.length > 0) {
renderers.value.forEach((renderer) => {
renderer.setMap(null);
if (polylines.value.length > 0) {
polylines.value.forEach((polyline) => {
polyline.setMap(null);
});
renderers.value = [];
polylines.value = [];
}
errorRuta.value = null;
};
@ -40,64 +40,81 @@ export function useDirectionsRoute() {
errorRuta.value = null;
try {
const directionsService = new google.maps.DirectionsService();
// Límite de la API de Google Maps: Origen, Destino, y hasta 23 waypoints (25 puntos total por request)
// Importar librerías necesarias de la nueva API
const { Route } = await google.maps.importLibrary("routes") as any;
// Límite de la API de Google Maps Routes: Origen, Destino, y hasta 25 intermediates
const maxPuntosPorChunk = 25;
const overlaps = 1;
// Iteramos sobre las paradas dividiéndolas en chunks con 1 punto en común ("overlap")
// para asegurar que las secciones se conecten correctamente.
for (let i = 0; i < paradas.length - 1; i += (maxPuntosPorChunk - overlaps)) {
const chunk = paradas.slice(i, i + maxPuntosPorChunk);
// Si el chunk es muy pequeño (último fragmento o vector final), detenemos
if (chunk.length < 2) break;
const origen = new google.maps.LatLng(chunk[0]!.latitud, chunk[0]!.longitud);
const destino = new google.maps.LatLng(chunk[chunk.length - 1]!.latitud, chunk[chunk.length - 1]!.longitud);
// Excluimos el primero y último para que sean los waypoints intermedios
const waypoints: google.maps.DirectionsWaypoint[] = chunk.slice(1, -1).map(p => ({
location: new google.maps.LatLng(p.latitud, p.longitud),
stopover: true
}));
const request: google.maps.DirectionsRequest = {
origin: origen,
destination: destino,
waypoints: waypoints,
travelMode: google.maps.TravelMode.DRIVING,
optimizeWaypoints: false
const origin = {
location: {
latLng: {
latitude: chunk[0]!.latitud,
longitude: chunk[0]!.longitud
}
}
};
try {
const response = await directionsService.route(request);
const renderer = new google.maps.DirectionsRenderer({
map: map,
suppressMarkers: true, // SIBU maneja los suyos propios
preserveViewport: true, // No auto centrar en cada tramo para evitar parpadeos visuales
polylineOptions: isPast ? {
strokeColor: '#FDE68A', // amarillo muy tenue
strokeWeight: 3,
strokeOpacity: 0.4
} : {
strokeColor: '#FBBF24', // amarillo principal
strokeWeight: 5,
strokeOpacity: 0.95
const destination = {
location: {
latLng: {
latitude: chunk[chunk.length - 1]!.latitud,
longitude: chunk[chunk.length - 1]!.longitud
}
}
};
const intermediates = chunk.slice(1, -1).map(p => ({
location: {
latLng: {
latitude: p.latitud,
longitude: p.longitud
}
}
}));
try {
const response = await Route.computeRoutes({
origin,
destination,
intermediates,
travelMode: 'DRIVE' as any, // 'DRIVE' es el nuevo estandar en computeRoutes
routingPreference: 'TRAFFIC_UNAWARE' as any,
polylineQuality: 'HIGH_QUALITY' as any,
polylineEncoding: 'ENCODED_POLYLINE' as any,
});
renderer.setDirections(response);
registrarRenderer(renderer);
if (response.routes && response.routes.length > 0) {
const route = response.routes[0];
if (route.polyline && route.polyline.encodedPolyline) {
const path = google.maps.geometry.encoding.decodePath(route.polyline.encodedPolyline);
const polyline = new google.maps.Polyline({
path: path,
map: map,
strokeColor: isPast ? '#FDE68A' : '#FBBF24',
strokeWeight: isPast ? 3 : 5,
strokeOpacity: isPast ? 0.4 : 0.95,
icons: isPast ? [{
icon: { path: 'M 0,-1 0,1', strokeOpacity: 1, scale: 2 },
offset: '0',
repeat: '10px'
}] : []
});
registrarPolyline(polyline);
}
}
} catch (err: any) {
console.warn(`SIBU | Tramo ${i} falló: `, err);
// La ruta continúa renderizando los siguientes tramos disponibles, no paramos todo.
console.warn(`SIBU | Tramo ${i} falló con Routes API: `, err);
}
// Retardo para evitar sobrecargar a la API y el error "OVER_QUERY_LIMIT"
await delay(300);
await delay(200);
}
} catch (err: any) {
errorRuta.value = `Error crítico al trazar la ruta: ${err.message || String(err)}`;