Skip to content

Commit eed201c

Browse files
committed
working with kevin
2 parents b4b6f71 + c55e5a1 commit eed201c

File tree

5 files changed

+570
-127
lines changed

5 files changed

+570
-127
lines changed

src/app/components/Map.tsx

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
/* eslint-disable arrow-body-style */
2+
/* eslint-disable max-len */
3+
/* eslint-disable @typescript-eslint/no-explicit-any */
4+
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
5+
/* eslint-disable @typescript-eslint/ban-types */
6+
7+
import React, { useRef, useState, useEffect } from 'react';
8+
import * as d3 from 'd3';
9+
10+
const Map = (props) => {
11+
const { snapshot } = props;
12+
console.log('MAP SNAPSHOT', snapshot);
13+
14+
// set the heights and width of the tree to be passed into treeMap function
15+
const width: number = 600;
16+
const height: number = 1100;
17+
18+
// this state allows the canvas to stay at the zoom level on multiple re-renders
19+
const [{ x, y, k }, setZoomState]: any = useState({ x: 0, y: 0, k: 0 });
20+
21+
useEffect(() => {
22+
setZoomState(d3.zoomTransform(d3.select('#canvas').node()));
23+
}, [snapshot]);
24+
25+
// this only clears the canvas if Visualizer is already rendered on the extension
26+
useEffect(() => {
27+
document.getElementById('canvas').innerHTML = '';
28+
29+
// creating the main svg container for d3 elements
30+
const svgContainer: any = d3
31+
.select('#canvas')
32+
.attr('width', width)
33+
.attr('height', height);
34+
35+
// creating a pseudo-class for reusability
36+
const g: any = svgContainer
37+
.append('g')
38+
.attr('transform', `translate(${x}, ${y}), scale(${k})`); // sets the canvas to the saved zoomState
39+
40+
//RE-WRITE ALGORITHIM For All Possible Snapshot Formats
41+
42+
// appState is the object that is passed into d3.hierarchy
43+
// const childrenArr = [];
44+
// if (snapshot.children[0].state.hooksState) {
45+
// snapshot.children[0].state.hooksState.forEach((el) =>
46+
// childrenArr.push(el)
47+
// );
48+
// }
49+
50+
// console.log('CHILDREN', childrenArr);
51+
52+
const appState: any = {
53+
name: ' Root',
54+
// pass in parsed data here
55+
// call the helper function passing in the most recent snapshot
56+
children: snapshot.children,
57+
};
58+
59+
console.log('STATE', appState);
60+
// creating the tree map
61+
const treeMap: any = d3.tree().nodeSize([width, height]);
62+
63+
// creating the nodes of the tree
64+
// pass
65+
const hierarchyNodes: any = d3.hierarchy(appState);
66+
67+
console.log('Hierarchy NODES', hierarchyNodes);
68+
69+
// calling the tree function with nodes created from data
70+
const finalMap: any = treeMap(hierarchyNodes);
71+
72+
console.log('FINAL MAP', finalMap);
73+
74+
// renders a flat array of objects containing all parent-child links
75+
// renders the paths onto the component
76+
let paths: any = finalMap.links();
77+
console.log('PATHS', paths);
78+
79+
// this creates the paths to each atom and its contents in the tree
80+
g.append('g')
81+
.attr('fill', 'none')
82+
.attr('stroke', '#646464')
83+
.attr('stroke-width', 5)
84+
.selectAll('path')
85+
.data(paths)
86+
.enter()
87+
.append('path')
88+
.attr(
89+
'd',
90+
d3
91+
.linkHorizontal()
92+
.x((d: any) => d.y)
93+
.y((d: any) => d.x)
94+
);
95+
96+
// returns a flat array of objects containing all the nodes and their information
97+
// renders nodes onto the canvas
98+
let nodes: any = hierarchyNodes.descendants();
99+
100+
// const node is used to create all the nodes
101+
// this segment places all the nodes on the canvas
102+
const node: any = g
103+
.append('g')
104+
.attr('stroke-linejoin', 'round') // no clue what this does
105+
.attr('stroke-width', 1)
106+
.selectAll('g')
107+
.data(nodes)
108+
.enter()
109+
.append('g')
110+
.attr('transform', (d: any) => `translate(${d.y}, ${d.x})`)
111+
.attr('class', 'atomNodes');
112+
113+
// for each node that got created, append a circle element
114+
node.append('circle').attr('fill', '#c300ff').attr('r', 50);
115+
116+
// for each node that got created, append a text element that displays the name of the node
117+
node
118+
.append('text')
119+
.attr('dy', '.31em')
120+
.attr('x', (d: any) => (d.children ? -75 : 75))
121+
.attr('text-anchor', (d: any) => (d.children ? 'end' : 'start'))
122+
.text((d: any) => d.data.name)
123+
.style('font-size', `2rem`)
124+
.style('fill', 'white')
125+
.clone(true)
126+
.lower()
127+
.attr('stroke', '#646464')
128+
.attr('stroke-width', 2);
129+
130+
// adding a mouseOver event handler to each node
131+
// only add popup text on nodes with no children
132+
// display the data in the node on hover
133+
node.on('mouseover', function (d: any, i: number): any {
134+
if (!d.children) {
135+
d3.select(this)
136+
.append('text')
137+
.text(JSON.stringify(d.data, undefined, 2))
138+
.style('fill', 'white')
139+
.attr('x', 75)
140+
.attr('y', 60)
141+
.style('font-size', '3rem')
142+
.attr('stroke', '#646464')
143+
.attr('id', `popup${i}`);
144+
}
145+
});
146+
147+
// add mouseOut event handler that removes the popup text
148+
node.on('mouseout', function (d: any, i: number): any {
149+
d3.select(`#popup${i}`).remove();
150+
});
151+
152+
// allows the canvas to be draggable
153+
node.call(
154+
d3
155+
.drag()
156+
.on('start', dragStarted)
157+
.on('drag', dragged)
158+
.on('end', dragEnded)
159+
);
160+
161+
// allows the canvas to be zoom-able
162+
svgContainer.call(
163+
d3
164+
.zoom()
165+
.extent([
166+
[0, 0],
167+
[width, height],
168+
])
169+
.scaleExtent([0, 8])
170+
.on('zoom', zoomed)
171+
);
172+
173+
// helper functions that help with dragging functionality
174+
function dragStarted(): any {
175+
d3.select(this).raise();
176+
g.attr('cursor', 'grabbing');
177+
}
178+
179+
function dragged(d: any): any {
180+
d3.select(this)
181+
.attr('dx', (d.x = d3.event.x))
182+
.attr('dy', (d.y = d3.event.y));
183+
}
184+
185+
function dragEnded(): any {
186+
g.attr('cursor', 'grab');
187+
}
188+
189+
// helper function that allows for zooming
190+
function zoomed(): any {
191+
g.attr('transform', d3.event.transform);
192+
}
193+
});
194+
195+
console.log('208');
196+
return (
197+
<div data-testid="canvas">
198+
<div className="Visualizer">
199+
<svg id="canvas"></svg>
200+
</div>
201+
</div>
202+
);
203+
};
204+
205+
export default Map;

0 commit comments

Comments
 (0)