tfrere's picture
tfrere HF Staff
update
6bda4a6
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 };
}