Spaces:
Configuration error
Configuration error
| import { useEffect, useRef } from 'react'; | |
| import * as d3 from 'd3'; | |
| import { getConfig } from '../config/mapConfig.js'; | |
| import { applyZoomTransform } from '../utils/mappingUtils.js'; | |
| /** | |
| * Hook pour gérer le comportement de zoom D3 | |
| */ | |
| export function useZoom(svgRef, baseGlyphSize, enabled = true, darkMode = false) { | |
| console.log('useZoom: Hook appelé avec baseGlyphSize:', baseGlyphSize); | |
| const zoomRef = useRef(null); | |
| const baseGlyphSizeRef = useRef(baseGlyphSize); | |
| const isInitializedRef = useRef(false); | |
| // Mettre à jour la référence du baseGlyphSize | |
| useEffect(() => { | |
| baseGlyphSizeRef.current = baseGlyphSize; | |
| }, [baseGlyphSize]); | |
| // Initialiser le zoom quand le SVG est prêt | |
| useEffect(() => { | |
| if (!enabled) { | |
| console.log('useZoom: Hook désactivé, sortie'); | |
| return; | |
| } | |
| // Éviter les initialisations multiples | |
| if (isInitializedRef.current) { | |
| console.log('useZoom: Déjà initialisé, sortie'); | |
| return; | |
| } | |
| const initializeZoom = () => { | |
| if (!svgRef.current) { | |
| console.log('useZoom: svgRef.current is null, en attente...'); | |
| return; | |
| } | |
| const svg = d3.select(svgRef.current); | |
| console.log('useZoom: SVG sélectionné', svg.node()); | |
| // Créer ou récupérer le groupe viewport | |
| let viewportGroup = svg.select('.viewport-group'); | |
| if (viewportGroup.empty()) { | |
| viewportGroup = svg.append('g').attr('class', 'viewport-group'); | |
| console.log('useZoom: Groupe viewport créé'); | |
| } else { | |
| console.log('useZoom: Groupe viewport existant trouvé'); | |
| } | |
| // Créer le comportement de zoom | |
| const zoom = d3.zoom() | |
| .scaleExtent(getConfig('zoom.scaleExtent', [0.3, 3.0])) | |
| .on('zoom', (event) => { | |
| console.log('useZoom: Événement de zoom déclenché', event.transform); | |
| // Appliquer la transformation directement sans limitation | |
| viewportGroup.attr('transform', event.transform); | |
| // Ajuster la taille du texte des centroïdes pour compenser le zoom | |
| const scale = event.transform.k; | |
| const fontSize = Math.max(8, 16 / scale); // Taille de base 16px, minimum 8px | |
| const strokeColor = darkMode ? '#000000' : '#ffffff'; | |
| viewportGroup.selectAll('.centroid-label') | |
| .attr('font-size', `${fontSize}px`) | |
| .attr('stroke-width', `${Math.max(1, 4 / scale)}px`) | |
| .attr('stroke', strokeColor); | |
| }) | |
| .on('start', () => { | |
| console.log('useZoom: Début de l\'interaction'); | |
| }) | |
| .on('end', () => { | |
| console.log('useZoom: Fin de l\'interaction'); | |
| }); | |
| // Appliquer le zoom au SVG | |
| svg.call(zoom); | |
| // Initialiser avec l'échelle configurée | |
| const initialScale = getConfig('zoom.initialScale', 0.8); | |
| const svgRect = svg.node().getBoundingClientRect(); | |
| const centerX = svgRect.width / 2; | |
| const centerY = svgRect.height / 2; | |
| // Créer la transformation initiale centrée | |
| const initialTransform = d3.zoomIdentity | |
| .translate(centerX * (1 - initialScale), centerY * (1 - initialScale)) | |
| .scale(initialScale); | |
| // Appliquer la transformation initiale | |
| svg.call(zoom.transform, initialTransform); | |
| console.log('useZoom: Zoom initialisé avec échelle:', initialScale); | |
| // Stocker la référence et marquer comme initialisé | |
| zoomRef.current = zoom; | |
| isInitializedRef.current = true; | |
| }; | |
| // Essayer d'initialiser immédiatement | |
| initializeZoom(); | |
| // Si ça n'a pas marché, essayer après un délai | |
| if (!svgRef.current) { | |
| const timer = setTimeout(initializeZoom, 100); | |
| return () => clearTimeout(timer); | |
| } | |
| // Nettoyer au démontage | |
| return () => { | |
| if (svgRef.current) { | |
| const svg = d3.select(svgRef.current); | |
| svg.on('.zoom', null); | |
| } | |
| // Nettoyer les références | |
| zoomRef.current = null; | |
| isInitializedRef.current = false; | |
| }; | |
| }, [enabled]); // Dépendance sur enabled | |
| const resetZoom = () => { | |
| if (zoomRef.current && svgRef.current && isInitializedRef.current) { | |
| const svg = d3.select(svgRef.current); | |
| const svgNode = svg.node(); | |
| const width = svgNode.clientWidth || window.innerWidth; | |
| const height = svgNode.clientHeight || window.innerHeight; | |
| const centerX = width / 2; | |
| const centerY = height / 2; | |
| const scale = getConfig('zoom.initialScale', 0.8); | |
| // Calculer la translation pour centrer la vue | |
| const translateX = centerX * (1 - scale); | |
| const translateY = centerY * (1 - scale); | |
| const resetTransform = d3.zoomIdentity | |
| .translate(translateX, translateY) | |
| .scale(scale); | |
| svg.transition().duration(getConfig('zoom.transitionDuration', 750)).call( | |
| zoomRef.current.transform, | |
| resetTransform | |
| ); | |
| console.log('useZoom: Reset zoom appliqué'); | |
| } | |
| }; | |
| return { resetZoom }; | |
| } | |