From 5a8bee52d57b0f215705f3a7efb654169f85a7ae Mon Sep 17 00:00:00 2001 From: dmolinari Date: Mon, 22 Sep 2025 09:08:43 -0300 Subject: [PATCH] Fix Arrastre Mapa en Zoom --- .../legislativas/nacionales/PanelNacional.css | 16 ++-- .../nacionales/components/MapaNacional.tsx | 77 +++++-------------- .../net9.0/Elecciones.Api.AssemblyInfo.cs | 2 +- 3 files changed, 29 insertions(+), 66 deletions(-) diff --git a/Elecciones-Web/frontend/src/features/legislativas/nacionales/PanelNacional.css b/Elecciones-Web/frontend/src/features/legislativas/nacionales/PanelNacional.css index fa4a518..837a2b0 100644 --- a/Elecciones-Web/frontend/src/features/legislativas/nacionales/PanelNacional.css +++ b/Elecciones-Web/frontend/src/features/legislativas/nacionales/PanelNacional.css @@ -296,7 +296,7 @@ } -/* --- MAPA Y ELEMENTOS ASOCIADOS (sin cambios) --- */ +/* --- MAPA Y ELEMENTOS ASOCIADOS --- */ .mapa-componente-container { width: 100%; height: 100%; @@ -329,6 +329,11 @@ transition: transform 0.75s ease-in-out; } +/* AÑADIDO: Desactivar la transición durante el arrastre */ +.rsm-zoomable-group.panning { + transition: none; +} + .panel-main-content.panel-collapsed .mapa-column { flex: 1 1 100%; } @@ -368,7 +373,6 @@ } .rsm-geography { - cursor: pointer; stroke: #000000; stroke-width: 0.25px; outline: none; @@ -579,18 +583,14 @@ /* --- ESTILOS DE CURSOR PARA EL ARRASTRE DEL MAPA --- */ .map-locked .rsm-geography { cursor: pointer; - /* Cursor normal de clic */ } .map-pannable .rsm-geography { cursor: grab; - /* Indica que el mapa se puede arrastrar */ } -.map-pannable .rsm-geography:active { - cursor: grabbing; - /* Indica que se está arrastrando */ -} +/* El cursor 'grabbing' se aplica automáticamente por el navegador durante el arrastre */ + /* --- MEDIA QUERY PARA RESPONSIVE (ENFOQUE FINAL CON CAPAS) --- */ @media (max-width: 800px) { diff --git a/Elecciones-Web/frontend/src/features/legislativas/nacionales/components/MapaNacional.tsx b/Elecciones-Web/frontend/src/features/legislativas/nacionales/components/MapaNacional.tsx index d531b8b..6cf3caf 100644 --- a/Elecciones-Web/frontend/src/features/legislativas/nacionales/components/MapaNacional.tsx +++ b/Elecciones-Web/frontend/src/features/legislativas/nacionales/components/MapaNacional.tsx @@ -1,3 +1,4 @@ +// src/features/legislativas/nacionales/components/MapaNacional.tsx import axios from 'axios'; import { Suspense, useState, useEffect, useCallback, useRef } from 'react'; import { useSuspenseQuery } from '@tanstack/react-query'; @@ -53,13 +54,14 @@ export const MapaNacional = ({ eleccionId, categoriaId, nivel, nombreAmbito, nom zoom: isMobileView ? 1.5 : 1.05, // 1.5 para móvil, 1.05 para desktop center: [-65, -40] as PointTuple }); + const [isPanning, setIsPanning] = useState(false); const initialProvincePositionRef = useRef<{ zoom: number, center: PointTuple } | null>(null); const containerRef = useRef(null); const lupaRef = useRef(null); const cabaPathRef = useRef(null); const isAnimatingRef = useRef(false); - const initialLoadRef = useRef(true); // Ref para controlar la carga inicial + const initialLoadRef = useRef(true); const [lupaStyle, setLupaStyle] = useState({ opacity: 0 }); @@ -80,10 +82,9 @@ export const MapaNacional = ({ eleccionId, categoriaId, nivel, nombreAmbito, nom useEffect(() => { if (nivel === 'pais') { setPosition({ - zoom: isMobileView ? 1.4 : 1.05, // 1.5 para móvil, 1.05 para desktop + zoom: isMobileView ? 1.4 : 1.05, center: [-65, -40] }); - // Reseteamos el ref initialProvincePositionRef.current = null; } else if (nivel === 'provincia') { const nombreNormalizado = normalizarTexto(nombreAmbito); @@ -103,11 +104,9 @@ export const MapaNacional = ({ eleccionId, categoriaId, nivel, nombreAmbito, nom } setPosition(provinceConfig); - - // --- Guardar el objeto de posición completo en el ref --- initialProvincePositionRef.current = provinceConfig; } - }, [nivel, nombreAmbito, geoDataNacional]); + }, [nivel, nombreAmbito, geoDataNacional, isMobileView]); const resultadosNacionalesPorNombre = new Map(mapaDataNacional.map(d => [normalizarTexto(d.ambitoNombre), d])); const nombreMunicipioSeleccionado = nivel === 'municipio' ? nombreAmbito : null; @@ -142,29 +141,18 @@ export const MapaNacional = ({ eleccionId, categoriaId, nivel, nombreAmbito, nom }; isAnimatingRef.current = true; - - const handleResize = () => { - if (!isAnimatingRef.current) { - updateLupaPosition(); - } - }; - + const handleResize = () => { if (!isAnimatingRef.current) updateLupaPosition(); }; const resizeObserver = new ResizeObserver(handleResize); - if (containerRef.current) { - resizeObserver.observe(containerRef.current); - } + if (containerRef.current) resizeObserver.observe(containerRef.current); let timerId: NodeJS.Timeout; - if (initialLoadRef.current && nivel === 'pais') { - // Carga inicial: posicionar inmediatamente timerId = setTimeout(() => { updateLupaPosition(); isAnimatingRef.current = false; }, 0); - initialLoadRef.current = false; // Marcar como ya cargado + initialLoadRef.current = false; } else { - // Transición de vuelta: esperar a que termine la animación timerId = setTimeout(() => { updateLupaPosition(); isAnimatingRef.current = false; @@ -172,77 +160,53 @@ export const MapaNacional = ({ eleccionId, categoriaId, nivel, nombreAmbito, nom } return () => { - if (containerRef.current) { - resizeObserver.unobserve(containerRef.current); - } + if (containerRef.current) resizeObserver.unobserve(containerRef.current); clearTimeout(timerId); isAnimatingRef.current = false; }; }, [position, nivel]); - // --- HANDLERS PARA EL ZOOM --- - const handleZoomIn = () => { - setPosition(prev => ({ - ...prev, - zoom: Math.min(prev.zoom * 1.8, 100) // Multiplica el zoom actual, con un límite - })); - }; + const handleZoomIn = () => setPosition(prev => ({ ...prev, zoom: Math.min(prev.zoom * 1.8, 100) })); - // --- Lógica de reseteo en handleZoomOut --- const handleZoomOut = () => { setPosition(prev => { const newZoom = Math.max(prev.zoom / 1.8, 1); const initialPos = initialProvincePositionRef.current; - - // Si estamos en una provincia Y el nuevo zoom es igual o menor que el inicial... - if (initialPos && newZoom <= initialPos.zoom) { - // ...reseteamos a la posición inicial guardada (zoom Y centro). - return initialPos; - } - - // Si no, solo actualizamos el zoom. + if (initialPos && newZoom <= initialPos.zoom) return initialPos; return { ...prev, zoom: newZoom }; }); }; const handleMoveEnd = (newPosition: { coordinates: PointTuple, zoom: number }) => { - // Solo actualizamos el centro (coordenadas), no el zoom, al arrastrar setPosition(prev => ({ ...prev, center: newPosition.coordinates })); + setIsPanning(false); }; const panEnabled = - //isMobileView && nivel === 'provincia' && initialProvincePositionRef.current !== null && position.zoom > initialProvincePositionRef.current.zoom && !nombreMunicipioSeleccionado; - const showZoomControls = nivel === 'provincia'; - - // --- FUNCIÓN DE FILTRO --- const filterInteractionEvents = (event: any) => { - // La librería pasa un objeto de evento que contiene el evento original del navegador. - // Si el evento original es de la rueda del ratón ('wheel'), siempre lo bloqueamos. - if (event.sourceEvent && event.sourceEvent.type === 'wheel') { - return false; - } - // Para cualquier otro evento (arrastre, etc.), la decisión depende de nuestra lógica `panEnabled`. + if (event.sourceEvent && event.sourceEvent.type === 'wheel') return false; return panEnabled; }; - // --- LÓGICA PARA DESHABILITAR EL BOTÓN --- + const showZoomControls = nivel === 'provincia'; const isZoomOutDisabled = (nivel === 'provincia' && initialProvincePositionRef.current && position.zoom <= initialProvincePositionRef.current.zoom) || (nivel === 'pais' && position.zoom <= (isMobileView ? 1.4 : 1.05)); + const mapContainerClasses = panEnabled ? 'mapa-componente-container map-pannable' : 'mapa-componente-container map-locked'; + return ( -
+
{showZoomControls && (
-
diff --git a/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/Elecciones.Api.AssemblyInfo.cs b/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/Elecciones.Api.AssemblyInfo.cs index 95523b7..d064c68 100644 --- a/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/Elecciones.Api.AssemblyInfo.cs +++ b/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/Elecciones.Api.AssemblyInfo.cs @@ -14,7 +14,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+7d2922aaeb546ad280af958d81394ab1715a3267")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3750d1a56d3311ec92c79dc6cb564a0b8a68239c")] [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")] [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]