Skip to content

Commit 86a5e02

Browse files
committed
working well; renamed and commented
1 parent 740458d commit 86a5e02

File tree

1 file changed

+56
-85
lines changed

1 file changed

+56
-85
lines changed

src/app/components/PerfView.jsx

Lines changed: 56 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable no-use-before-define */
12
/* eslint-disable react/no-this-in-sfc */
23
/* eslint-disable no-unused-vars */
34
/* eslint-disable react/prop-types */
@@ -19,147 +20,117 @@ import React, { useEffect, useState, useRef, useCallback } from 'react';
1920
import * as d3 from 'd3';
2021
// import { addNewSnapshots } from '../actions/actions';
2122

22-
// const windowRef = useRef(null);
23-
// const winWidth = null;
24-
// const winHeight = null;
2523

26-
// useEffect(() => {
27-
// if (windowRef.current) {
28-
// winWidth = windowRef.current.offsetHeight;
29-
// winHeight = windowRef.current.offsetWidth;
30-
// console.log('** SETTING WINDOW SIZES: ', winWidth, winHeight);
31-
// }
32-
// }, [windowRef]);
33-
34-
const PerfView = ({ snapshots, viewIndex }) => {
35-
const [chartData, updateChartData] = useState(snapshots[snapshots.length - 1]);
24+
const PerfView = ({ snapshots, viewIndex, width = 600, height = 600 }) => {
25+
console.log('***** constructor *****');
3626
const svgRef = useRef(null);
3727

38-
// Todo: implement update functions...
39-
const [curZoom, setZoom] = useState(null);
40-
const [width, setWidth] = useState(600);
41-
const [height, setHeight] = useState(600);
28+
// Figure out which snapshot index to use
29+
let indexToDisplay = null;
30+
if (viewIndex < 0) indexToDisplay = snapshots.length - 1;
31+
else indexToDisplay = viewIndex;
4232

43-
// set up color scaling function
44-
const color = d3.scaleLinear()
33+
// Set up color scaling function
34+
const colorScale = d3.scaleLinear()
4535
.domain([0, 7])
4636
.range(['hsl(152,80%,80%)', 'hsl(228,30%,40%)'])
4737
.interpolate(d3.interpolateHcl);
4838

49-
// set up circle-packing layout function
39+
// Set up circle-packing layout function
5040
const packFunc = useCallback(data => {
5141
return d3.pack()
5242
.size([width, height])
5343
.padding(3)(d3.hierarchy(data)
54-
.sum(d => {
55-
// console.log('in pack func. d=', d);
56-
return d.componentData.actualDuration;
57-
})
58-
.sort((a, b) => {
59-
// console.log('in sort func. a&b=', a, b);
60-
return b.value - a.value;
61-
}));
44+
.sum(d => { return d.componentData.actualDuration; })
45+
.sort((a, b) => { return b.value - a.value; }));
6246
}, [width, height]);
6347

64-
// first run, or user has made changes in their app; clear old tree and get current chartData
48+
// If indexToDisplay changes, clear old tree nodes
6549
useEffect(() => {
66-
console.log('PerfView -> snapshots', snapshots);
67-
console.log('Current viewIndex: ', viewIndex);
68-
for (let i = 0; i < snapshots.length; i++) {
69-
console.log(`SNAPSHOT[${i}] App actualDuration:`, snapshots[i].children[0].componentData.actualDuration);
70-
}
71-
72-
// clear old tree
50+
console.log('***** useEffect - CLEARING')
7351
while (svgRef.current.hasChildNodes()) {
7452
svgRef.current.removeChild(svgRef.current.lastChild);
7553
}
76-
77-
let indexToDisplay = null;
78-
if (viewIndex < 0) indexToDisplay = snapshots.length - 1;
79-
else indexToDisplay = viewIndex;
80-
81-
updateChartData(snapshots[indexToDisplay]);
82-
console.log(`Using snapshots[${indexToDisplay}]`);
83-
}, [svgRef, viewIndex, snapshots, chartData]);
54+
}, [indexToDisplay, svgRef]);
8455

8556
useEffect(() => {
86-
console.log('PerfView -> chartData', chartData);
57+
console.log(`***** useEffect - MAIN -> snapshots[${indexToDisplay}]`, snapshots[indexToDisplay]);
8758

88-
// generate tree with our data
89-
const packedRoot = packFunc(chartData);
90-
// console.log('PerfView -> packedRoot', packedRoot);
59+
// Generate tree with our data
60+
const packedRoot = packFunc(snapshots[indexToDisplay]);
9161

92-
// initial focus points at root of tree
93-
let focus = packedRoot;
62+
// Set initial focus root node
63+
let curFocus = packedRoot;
64+
65+
// View [x, y, r]
9466
let view;
9567

96-
// set up viewBox dimensions and onClick for parent svg
68+
// Set up viewBox dimensions and onClick for parent svg
9769
const svg = d3.select(svgRef.current)
9870
.attr('viewBox', `-${width / 2} -${height / 2} ${width} ${height}`)
99-
.on('click', () => zoom(packedRoot));
71+
.on('click', () => zoomToNode(packedRoot));
10072

101-
// connect circles below root to data
73+
// Connect circles below root to data
10274
const node = svg.append('g')
10375
.selectAll('circle')
10476
.data(packedRoot.descendants().slice(1))
10577
.enter().append('circle')
106-
.attr('fill', d => (d.children ? color(d.depth) : 'white'))
78+
.attr('fill', d => (d.children ? colorScale(d.depth) : 'white'))
10779
.attr('pointer-events', d => (!d.children ? 'none' : null))
10880
.on('mouseover', () => d3.select(this).attr('stroke', '#000'))
10981
.on('mouseout', () => d3.select(this).attr('stroke', null))
110-
.on('click', d => focus !== d && (zoom(d), d3.event.stopPropagation()));
82+
.on('click', d => curFocus !== d && (zoomToNode(d), d3.event.stopPropagation()));
11183

112-
// console.log('PerfView -> node', node);
113-
// console.log('packedRoot.descendants()', packedRoot.descendants());
114-
115-
// generate text labels
84+
// Generate text labels. Set (only) root to visible initially
11685
const label = svg.append('g')
11786
.attr('class', 'perf-chart-labels')
11887
.selectAll('text')
11988
.data(packedRoot.descendants())
12089
.enter().append('text')
12190
.style('fill-opacity', d => (d.parent === packedRoot ? 1 : 0))
12291
.style('display', d => (d.parent === packedRoot ? 'inline' : 'none'))
123-
.text(d => {
124-
// console.log('generating text label for d: ', d);
125-
return `${d.data.name}: ${Number.parseFloat(d.data.componentData.actualDuration).toFixed(2)}ms`;
126-
});
92+
.text(d => `${d.data.name}: \
93+
${Number.parseFloat(d.data.componentData.actualDuration).toFixed(2)}ms`);
12794

95+
// Remove any unused nodes
12896
label.exit().remove();
12997
node.exit().remove();
13098

131-
// jump to default zoom state
132-
zoomTo([packedRoot.x, packedRoot.y, packedRoot.r * 2]);
99+
// Zoom size of nodes and labels to focus view on root node
100+
zoomViewArea([packedRoot.x, packedRoot.y, packedRoot.r * 2]);
133101

134-
function zoomTo(v) {
102+
// Zoom/relocated nodes and labels based on dimensions given [x, y, r]
103+
function zoomViewArea(newXYR) {
135104
// console.log("zoomTo -> v", v);
136-
const k = width / v[2];
137-
view = v;
138-
label.attr('transform', d => `translate(${(d.x - v[0]) * k},${(d.y - v[1]) * k})`);
139-
node.attr('transform', d => `translate(${(d.x - v[0]) * k},${(d.y - v[1]) * k})`);
105+
const k = width / newXYR[2];
106+
view = newXYR;
107+
label.attr('transform', d => `translate(${(d.x - newXYR[0]) * k},${(d.y - newXYR[1]) * k})`);
108+
node.attr('transform', d => `translate(${(d.x - newXYR[0]) * k},${(d.y - newXYR[1]) * k})`);
140109
node.attr('r', d => d.r * k);
141110
}
142111

143-
function zoom(d) {
112+
// Transition visibility of labels
113+
function zoomToNode(newFocus) {
144114
// console.log("zoom -> d", d);
145-
const focus0 = focus;
146-
focus = d;
147115

148116
const transition = svg.transition()
149-
.duration(d3.event.altKey ? 7500 : 750)
150-
.tween('zoom', d => {
151-
const i = d3.interpolateZoom(view, [focus.x, focus.y, focus.r * 2]);
152-
return t => zoomTo(i(t));
153-
});
154-
155-
label
156-
.filter(function (d) { return d.parent === focus || this.style.display === 'inline'; })
117+
.duration(d3.event.altKey ? 7500 : 750)
118+
.tween('zoom', d => {
119+
const i = d3.interpolateZoom(view, [newFocus.x, newFocus.y, newFocus.r * 2]);
120+
return t => zoomViewArea(i(t));
121+
});
122+
123+
// Grab all nodes that were previously displayed, or who's parent is the new target newFocus
124+
// Transition their labels to visible or not
125+
label.filter(function (d) { console.log('label filtering. d=', d); return d.parent === newFocus || this.style.display === 'inline'; })
157126
.transition(transition)
158-
.style('fill-opacity', d => (d.parent === focus ? 1 : 0))
159-
.on('start', function (d) { if (d.parent === focus) this.style.display = 'inline'; })
160-
.on('end', function (d) { if (d.parent !== focus) this.style.display = 'none'; });
127+
.style('fill-opacity', d => (d.parent === newFocus ? 1 : 0))
128+
.on('start', function (d) { if (d.parent === newFocus) this.style.display = 'inline'; })
129+
.on('end', function (d) { if (d.parent !== newFocus) this.style.display = 'none'; });
130+
131+
curFocus = newFocus;
161132
}
162-
}, [chartData, color, packFunc, width, height]);
133+
}, [colorScale, packFunc, width, height, indexToDisplay, snapshots]);
163134

164135
return <svg className="perfContainer" ref={svgRef} />;
165136
};

0 commit comments

Comments
 (0)