File size: 5,128 Bytes
6bda4a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
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 };
}