File size: 3,181 Bytes
b3f0c1a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { useEffect, useRef } from 'react';
import * as d3 from 'd3';

/**
 * Simplified zoom hook for FontMapV2
 */
export function useZoomV2(svgRef, darkMode = false) {
    const zoomRef = useRef(null);
    const isInitializedRef = useRef(false);

    useEffect(() => {
        if (isInitializedRef.current) {
            return;
        }

        const initializeZoom = () => {
            if (!svgRef.current) {
                console.log('useZoomV2: SVG not ready, retrying...');
                return false;
            }

            const svg = d3.select(svgRef.current);

            const viewportGroup = svg.select('.viewport-group');
            if (viewportGroup.empty()) {
                console.error('useZoomV2: viewport-group not found! Zoom will not work.');
                return false;
            }

            console.log('useZoomV2: Found viewport-group, setting up zoom...');

            // Create zoom behavior
            const zoom = d3.zoom()
                .scaleExtent([0.3, 5.0])
                .on('zoom', (event) => {
                    viewportGroup.attr('transform', event.transform);
                });

            // Apply zoom to SVG
            svg.call(zoom);

            // Calculate initial center based on viewport size
            const svgRect = svg.node().getBoundingClientRect();
            const centerX = svgRect.width / 2;
            const centerY = svgRect.height / 2;

            // Start at 80% zoom, centered
            const initialScale = 0.8;
            const initialTransform = d3.zoomIdentity
                .translate(centerX, centerY)
                .scale(initialScale)
                .translate(-1000, -1000); // Center of data space (2000x2000 with 50px padding)

            svg.call(zoom.transform, initialTransform);

            zoomRef.current = zoom;
            isInitializedRef.current = true;
            console.log('useZoomV2: Zoom initialized successfully');
            return true;
        };

        // Try to initialize immediately
        if (!initializeZoom()) {
            // If failed, retry after a short delay
            const timer = setTimeout(() => {
                initializeZoom();
            }, 100);

            return () => clearTimeout(timer);
        }

        return () => {
            if (svgRef.current) {
                d3.select(svgRef.current).on('.zoom', null);
            }
            zoomRef.current = null;
            isInitializedRef.current = false;
        };
    }, [svgRef, darkMode]);

    const resetZoom = () => {
        if (zoomRef.current && svgRef.current) {
            const svg = d3.select(svgRef.current);
            const width = svg.node().clientWidth;
            const height = svg.node().clientHeight;

            const centerX = width / 2;
            const centerY = height / 2;
            const scale = 0.8;

            const resetTransform = d3.zoomIdentity
                .translate(centerX, centerY)
                .scale(scale)
                .translate(-1000, -1000);

            svg.transition().duration(750).call(zoomRef.current.transform, resetTransform);
        }
    };

    return { resetZoom };
}