Skip to content

Commit d5f1708

Browse files
authored
Merge pull request #55 from oslabs-beta/bryan/d3-tooltip
Bryan/d3 tooltip
2 parents bce545f + 9c88715 commit d5f1708

File tree

2 files changed

+195
-156
lines changed

2 files changed

+195
-156
lines changed

src/app/components/Chart.jsx

Lines changed: 161 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import React, { Component } from 'react';
22
import '../styles/components/_d3Tree.scss';
33
import * as d3 from 'd3';
44

5-
let root;
5+
var root={};
6+
let duration = 750;
7+
68

79
class Chart extends Component {
810
constructor(props) {
@@ -14,189 +16,203 @@ class Chart extends Component {
1416
this.maked3Tree();
1517
}
1618

17-
componentWillUpdate(prevProps) {
18-
if (this.props.snapshot !== prevProps.snapshot) {
19-
root = JSON.parse(JSON.stringify(prevProps.snapshot));
20-
this.maked3Tree();
21-
}
19+
componentWillUpdate(newProps){
20+
if(this.props.snapshot !== newProps.snapshot){
21+
root = JSON.parse(JSON.stringify(newProps.snapshot));
22+
this.maked3Tree();
23+
}
2224
}
23-
25+
2426
removed3Tree() {
2527
const { anchor } = this.refs;
2628
while (anchor.hasChildNodes()) {
2729
anchor.removeChild(anchor.lastChild);
2830
}
2931
}
30-
31-
maked3Tree() {
32+
33+
maked3Tree(){
3234
this.removed3Tree();
35+
duration=0;
36+
37+
var margin = {top: 20, right: 120, bottom: 20, left: 120},
38+
width = 960 - margin.right - margin.left,
39+
height = 800 - margin.top - margin.bottom;
3340

34-
const margin = {
35-
top: 20,
36-
right: 120,
37-
bottom: 20,
38-
left: 120,
39-
};
40-
const width = 960 - margin.right - margin.left;
41-
const height = 800 - margin.top - margin.bottom;
41+
var i = 0;
4242

43-
let i = 0;
44-
const duration = 750;
43+
var tree = d3.layout.tree()
44+
.size([400, 400]);
4545

46-
const tree = d3.layout.tree().size([height, width]);
46+
var diagonal = d3.svg.diagonal()
47+
.projection(function(d) { return [d.y, d.x]; });
4748

48-
const diagonal = d3.svg.diagonal().projection(d => [d.y, d.x]);
49+
var svg = d3.select(this.refs.anchor).append("svg")
50+
.attr("width", width + margin.right + margin.left)
51+
.attr("height", height + margin.top + margin.bottom)
52+
.append("g")
53+
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
4954

50-
const svg = d3
51-
.select(this.refs.anchor)
52-
.append('svg')
53-
.attr('width', width + margin.right + margin.left)
54-
.attr('height', height + margin.top + margin.bottom)
55-
.append('g')
56-
.attr('transform', `translate(${margin.left},${margin.top})`);
55+
// Add tooltip div
56+
var div = d3.select("body").append("div")
57+
.attr("class", "tooltip")
58+
.style("opacity", 1e-6)
59+
.on("mouseover", tipMouseover)
60+
.on("mouseout", tipMouseout)
5761

5862
root.x0 = height / 2;
5963
root.y0 = 0;
60-
64+
6165
function update(source) {
62-
// Compute the new tree layout.
63-
const nodes = tree.nodes(root).reverse();
64-
const links = tree.links(nodes);
65-
66-
// Normalize for fixed-depth.
67-
nodes.forEach((d) => {
68-
d.y = d.depth * 180;
69-
});
70-
71-
// Update the nodes…
72-
const node = svg.selectAll('g.node').data(nodes, d => d.id || (d.id = ++i));
73-
74-
// Enter any new nodes at the parent's previous position.
75-
const nodeEnter = node
76-
.enter()
77-
.append('g')
78-
.attr('class', 'node')
79-
.attr('transform', d => `translate(${source.y0},${source.x0})`)
80-
.on('click', click)
81-
.on('mouseover', mouseover)
82-
.on('mouseout', mouseout);
83-
84-
nodeEnter
85-
.append('circle')
86-
.attr('r', 1e-6)
87-
.style('fill', d => (d._children ? 'lightsteelblue' : '#fff'));
88-
89-
nodeEnter
90-
.append('text')
91-
.attr('x', d => (d.children || d._children ? -10 : 10))
92-
.attr('dy', '.35em')
93-
.attr('text-anchor', d => (d.children || d._children ? 'end' : 'start'))
94-
.text(d => d.name)
95-
.style('fill-opacity', 1e-6);
96-
97-
// Transition nodes to their new position.
98-
const nodeUpdate = node
99-
.transition()
100-
.duration(duration)
101-
.attr('transform', d => `translate(${d.y},${d.x})`);
102-
103-
nodeUpdate
104-
.select('circle')
105-
.attr('r', 4.5)
106-
.style('fill', d => (d._children ? 'lightsteelblue' : '#fff'));
107-
108-
nodeUpdate.select('text').style('fill-opacity', 1);
109-
110-
// Transition exiting nodes to the parent's new position.
111-
const nodeExit = node
112-
.exit()
113-
.transition()
114-
.duration(duration)
115-
.attr('transform', d => `translate(${source.y},${source.x})`)
116-
.remove();
117-
118-
nodeExit.select('circle').attr('r', 1e-6);
119-
120-
nodeExit.select('text').style('fill-opacity', 1e-6);
121-
122-
// Update the links…
123-
const link = svg.selectAll('path.link').data(links, d => d.target.id);
124-
125-
// Enter any new links at the parent's previous position.
126-
link
127-
.enter()
128-
.insert('path', 'g')
129-
.attr('class', 'link')
130-
.attr('d', (d) => {
131-
const o = { x: source.x0, y: source.y0 };
132-
return diagonal({ source: o, target: o });
133-
});
134-
135-
// Transition links to their new position.
136-
link
137-
.transition()
138-
.duration(duration)
139-
.attr('d', diagonal);
140-
141-
// Transition exiting nodes to the parent's new position.
142-
link
143-
.exit()
144-
.transition()
145-
.duration(duration)
146-
.attr('d', (d) => {
147-
const o = { x: source.x, y: source.y };
148-
return diagonal({ source: o, target: o });
149-
})
150-
.remove();
151-
152-
// Stash the old positions for transition.
153-
nodes.forEach((d) => {
66+
// Compute the new tree layout.
67+
var nodes = tree.nodes(root).reverse(),
68+
links = tree.links(nodes);
69+
70+
// Normalize for fixed-depth.
71+
nodes.forEach(function(d) { d.y = d.depth * 180; });
72+
73+
// Update the nodes…
74+
var node = svg.selectAll("g.node")
75+
.data(nodes, function(d) { return d.id || (d.id = ++i); });
76+
77+
// Enter any new nodes at the parent's previous position.
78+
var nodeEnter = node.enter().append("g")
79+
.attr("class", "node")
80+
.attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
81+
.on("click", click)
82+
.on("mouseover", mouseover)
83+
.on("mouseout", mouseout)
84+
.on("mousemove", function(d){mousemove(d);});
85+
86+
87+
nodeEnter.append("circle")
88+
.attr("r", 1e-6)
89+
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
90+
91+
nodeEnter.append("text")
92+
.attr("x", function(d) { return d.children || d._children ? -10 : 10; })
93+
.attr("dy", ".35em")
94+
.attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
95+
.text(function(d) { return d.name; })
96+
.style('fill', '#6FB3D2')
97+
.style("fill-opacity", 1e-6);
98+
99+
// Transition nodes to their new position.
100+
var nodeUpdate = node.transition()
101+
.duration(duration)
102+
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
103+
104+
nodeUpdate.select("circle")
105+
.attr("r", 7)
106+
.style("fill", function(d) { return d._children ? "#A1C658" : "#D381C3"; });
107+
108+
nodeUpdate.select("text")
109+
.style("fill-opacity", 1);
110+
111+
// Transition exiting nodes to the parent's new position.
112+
var nodeExit = node.exit().transition()
113+
.duration(duration)
114+
.attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
115+
.remove();
116+
117+
nodeExit.select("circle")
118+
.attr("r", 1e-6);
119+
120+
nodeExit.select("text")
121+
.style("fill-opacity", 1e-6);
122+
123+
// Update the links…
124+
var link = svg.selectAll("path.link")
125+
.data(links, function(d) { return d.target.id; });
126+
127+
// Enter any new links at the parent's previous position.
128+
link.enter().insert("path", "g")
129+
.attr("class", "link")
130+
.attr("d", function(d) {
131+
var o = {x: source.x0, y: source.y0};
132+
return diagonal({source: o, target: o});
133+
});
134+
135+
// Transition links to their new position.
136+
link.transition()
137+
.duration(duration)
138+
.attr("d", diagonal);
139+
140+
// Transition exiting nodes to the parent's new position.
141+
link.exit().transition()
142+
.duration(duration)
143+
.attr("d", function(d) {
144+
var o = {x: source.x, y: source.y};
145+
return diagonal({source: o, target: o});
146+
})
147+
.remove();
148+
149+
// Stash the old positions for transition.
150+
nodes.forEach(function(d) {
154151
d.x0 = d.x;
155152
d.y0 = d.y;
156-
});
153+
});
157154
}
158-
155+
159156
// Toggle children on click.
160157
function click(d) {
161-
if (d.children) {
158+
if (d.children) {
162159
d._children = d.children;
163160
d.children = null;
164-
} else {
161+
} else {
165162
d.children = d._children;
166163
d._children = null;
167-
}
168-
update(d);
164+
}
165+
update(d);
169166
}
170167

171168
// Show state on mouse over
172-
function mouseover(d) {
173-
d3.select(this)
174-
.append('text')
175-
.attr('class', 'hover')
176-
.attr('transform', d => 'translate(5, -10)')
177-
.text(d.state === undefined ? '' : JSON.stringify(d.state));
169+
function mouseover() {
170+
div.transition()
171+
.duration(300)
172+
.style("display", "block")
173+
.style("opacity", 1)
174+
}
175+
176+
function mouseout() {
177+
div.transition()
178+
.duration(3000)
179+
.style("opacity", 1e-6)
180+
.style("display", "none");
178181
}
179182

180-
// Toggle children on click.
181-
function mouseout(d) {
182-
d3.select(this)
183-
.select('text.hover')
184-
.remove();
183+
function tipMouseover(){
184+
div.transition()
185+
.duration(300)
186+
.style("opacity", 1);
185187
}
186188

189+
function tipMouseout() {
190+
div.transition()
191+
.duration(3000)
192+
.style("opacity", 1e-6)
193+
.style("display", "none");
194+
}
195+
196+
function mousemove(d){
197+
div
198+
.text(d.state == undefined ? 'No state found' : JSON.stringify(d.state,null,4))
199+
.style("left", (d3.event.pageX ) + "px")
200+
.style("top", (d3.event.pageY) + "px");
201+
}
202+
187203
function collapse(d) {
188-
if (d.children) {
204+
if (d.children) {
189205
d._children = d.children;
190206
d._children.forEach(collapse);
191207
d.children = null;
192-
}
208+
}
193209
}
194-
195-
// root.children.forEach(collapse);
210+
196211
update(root);
197-
198-
// d3.select(self.frameElement).style("height", "800px");
199-
}
212+
duration = 750;
213+
214+
// root.children.forEach(collapse);
215+
}
200216

201217
render() {
202218
return <div ref="anchor" className="d3Container" width="100%" />;

0 commit comments

Comments
 (0)