Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
50
rated 0 times [  51] [ 1]  / answers: 1 / hits: 29123  / 9 Years ago, thu, june 18, 2015, 12:00:00

I am a noob in web-development. I'm trying to create a tree-like hierarchical company org chart. I tried both google's visualization chart and Mike Bostock's D3 Reingold tree.



I want these features :




  • tree structure : either top-down (google) or left-right (D3)

  • online/dynamic : viewable in browser and able to read data from json (both google & D3), not static visio or ppt diagram

  • collapsible : able to hide subtrees (both)

  • space-adjusting : nodes should fill visible area, to reduce scrolling (only D3)

  • attributes : display name, title & possibly picture (only google)



Above I've marked which tool allows which features, afaik.

I prefer the D3 version because it looks cool.

I can modify the .json to include additional fields (title, url to photo etc.) - here is a sample



My question is - how do I modify the D3 code to display an employee's name, then title in the next line, and maybe picture too ?



Or if that's not feasible - how do I modify the google code to automatically adjust spacing, so that all children of a node are close together, and I don't have to horizontally scroll ?


More From » html

 Answers
7

Here's a quick example. It modifies this example, to add in first name, last name, a title and a picture.





<!DOCTYPE html>
<meta charset=utf-8>
<style>

.node {
cursor: pointer;
}

.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}

.node text {
font: 10px sans-serif;
}

.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
}

</style>
<body>
<script src=https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js></script>
<script>

var margin = {top: 20, right: 120, bottom: 20, left: 120},
width = 960 - margin.right - margin.left,
height = 300 - margin.top - margin.bottom;

var i = 0,
duration = 750,
root;

var tree = d3.layout.tree()
.size([height, width]);

var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.y, d.x]; });

var svg = d3.select(body).append(svg)
.attr(width, width + margin.right + margin.left)
.attr(height, height + margin.top + margin.bottom)
.append(g)
.attr(transform, translate( + margin.left + , + margin.top + ));


var data = {
fname: Rachel,
lname: Rogers,
title: CEO,
photo: http://lorempixel.com/60/60/cats/1,
children: [{
fname: Bob,
lname: Smith,
title: President,
photo: http://lorempixel.com/60/60/cats/2,
children: [{
fname: Mary,
lname: Jane,
title: Vice President,
photo: http://lorempixel.com/60/60/cats/3,
children: [{
fname: Bill,
lname: August,
title: Dock Worker,
photo: http://lorempixel.com/60/60/cats/4
}, {
fname: Reginald,
lname: Yoyo,
title: Line Assembly,
photo: http://lorempixel.com/60/60/cats/5
}]
}, {
fname: Nathan,
lname: Ringwald,
title: Comptroller,
photo: http://lorempixel.com/60/60/cats/6
}]
}]
}

root = data;
root.x0 = height / 2;
root.y0 = 0;

function collapse(d) {
if (d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}

root.children.forEach(collapse);
update(root);

function update(source) {

// Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);

// Normalize for fixed-depth.
nodes.forEach(function(d) { d.y = d.depth * 180; });

// Update the nodes…
var node = svg.selectAll(g.node)
.data(nodes, function(d) { return d.id || (d.id = ++i); });

// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append(g)
.attr(class, node)
.attr(transform, function(d) { return translate( + source.y0 + , + source.x0 + ); })
.on(click, click);

// add picture
nodeEnter
.append('defs')
.append('pattern')
.attr('id', function(d,i){
return 'pic_' + d.fname + d.lname;
})
.attr('height',60)
.attr('width',60)
.attr('x',0)
.attr('y',0)
.append('image')
.attr('xlink:href',function(d,i){
return d.photo;
})
.attr('height',60)
.attr('width',60)
.attr('x',0)
.attr('y',0);

nodeEnter.append(circle)
.attr(r, 1e-6)
.style(fill, function(d) { return d._children ? lightsteelblue : #fff; });

var g = nodeEnter.append(g);

g.append(text)
.attr(x, function(d) { return d.children || d._children ? -35 : 35; })
.attr(dy, 1.35em)
.attr(text-anchor, function(d) { return d.children || d._children ? end : start; })
.text(function(d) { return d.fname + + d.lname; })
.style(fill-opacity, 1e-6);

g.append(text)
.attr(x, function(d) { return d.children || d._children ? -35 : 35; })
.attr(dy, 2.5em)
.attr(text-anchor, function(d) { return d.children || d._children ? end : start; })
.text(function(d) { return d.title; })
.style(fill-opacity, 1e-6);

// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr(transform, function(d) { return translate( + d.y + , + d.x + ); });

nodeUpdate.select(circle)
.attr(r, 30)
.style(fill, function(d,i){
return 'url(#pic_' + d.fname + d.lname+')';
});

nodeUpdate.selectAll(text)
.style(fill-opacity, 1);

// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr(transform, function(d) { return translate( + source.y + , + source.x + ); })
.remove();

nodeExit.select(circle)
.attr(r, 1e-6);

nodeExit.select(text)
.style(fill-opacity, 1e-6);

// Update the links…
var link = svg.selectAll(path.link)
.data(links, function(d) { return d.target.id; });

// Enter any new links at the parent's previous position.
link.enter().insert(path, g)
.attr(class, link)
.attr(d, function(d) {
var o = {x: source.x0, y: source.y0};
return diagonal({source: o, target: o});
});

// Transition links to their new position.
link.transition()
.duration(duration)
.attr(d, diagonal);

// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr(d, function(d) {
var o = {x: source.x, y: source.y};
return diagonal({source: o, target: o});
})
.remove();

// Stash the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}

// Toggle children on click.
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}

</script>








Reversed Direction:





<!DOCTYPE html>
<meta charset=utf-8>
<style>

.node {
cursor: pointer;
}

.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}

.node text {
font: 10px sans-serif;
}

.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
}

</style>
<body>
<script src=https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js></script>
<script>

var margin = {top: 20, right: 120, bottom: 20, left: 120},
width = 960 - margin.right - margin.left,
height = 300 - margin.top - margin.bottom;

var i = 0,
duration = 750,
root;

var tree = d3.layout.tree()
.size([height, width]);

var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.x, d.y]; });

var svg = d3.select(body).append(svg)
.attr(width, width + margin.right + margin.left)
.attr(height, height + margin.top + margin.bottom)
.append(g)
.attr(transform, translate( + margin.left + , + margin.top + ));


var data = {
fname: Rachel,
lname: Rogers,
title: CEO,
photo: http://lorempixel.com/60/60/cats/1,
children: [{
fname: Bob,
lname: Smith,
title: President,
photo: http://lorempixel.com/60/60/cats/2,
children: [{
fname: Mary,
lname: Jane,
title: Vice President,
photo: http://lorempixel.com/60/60/cats/3,
children: [{
fname: Bill,
lname: August,
title: Dock Worker,
photo: http://lorempixel.com/60/60/cats/4
}, {
fname: Reginald,
lname: Yoyo,
title: Line Assembly,
photo: http://lorempixel.com/60/60/cats/5
}]
}, {
fname: Nathan,
lname: Ringwald,
title: Comptroller,
photo: http://lorempixel.com/60/60/cats/6
}]
}]
}

root = data;
root.x0 = height / 2;
root.y0 = 0;

function collapse(d) {
if (d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}

root.children.forEach(collapse);
update(root);

function update(source) {

// Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);

// Normalize for fixed-depth.
nodes.forEach(function(d) { d.y = d.depth * 180; });

// Update the nodes…
var node = svg.selectAll(g.node)
.data(nodes, function(d) { return d.id || (d.id = ++i); });

// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append(g)
.attr(class, node)
.attr(transform, function(d) { return translate( + source.x0 + , + source.y0 + ); })
.on(click, click);

// add picture
nodeEnter
.append('defs')
.append('pattern')
.attr('id', function(d,i){
return 'pic_' + d.fname + d.lname;
})
.attr('height',60)
.attr('width',60)
.attr('x',0)
.attr('y',0)
.append('image')
.attr('xlink:href',function(d,i){
return d.photo;
})
.attr('height',60)
.attr('width',60)
.attr('x',0)
.attr('y',0);

nodeEnter.append(circle)
.attr(r, 1e-6)
.style(fill, function(d) { return d._children ? lightsteelblue : #fff; });

var g = nodeEnter.append(g);

g.append(text)
.attr(x, function(d) { return d.children || d._children ? -35 : 35; })
.attr(dy, 1.35em)
.attr(text-anchor, function(d) { return d.children || d._children ? end : start; })
.text(function(d) { return d.fname + + d.lname; })
.style(fill-opacity, 1e-6);

g.append(text)
.attr(x, function(d) { return d.children || d._children ? -35 : 35; })
.attr(dy, 2.5em)
.attr(text-anchor, function(d) { return d.children || d._children ? end : start; })
.text(function(d) { return d.title; })
.style(fill-opacity, 1e-6);

// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr(transform, function(d) { return translate( + d.x + , + d.y + ); });

nodeUpdate.select(circle)
.attr(r, 30)
.style(fill, function(d,i){
return 'url(#pic_' + d.fname + d.lname+')';
});

nodeUpdate.selectAll(text)
.style(fill-opacity, 1);

// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr(transform, function(d) { return translate( + source.x + , + source.y + ); })
.remove();

nodeExit.select(circle)
.attr(r, 1e-6);

nodeExit.select(text)
.style(fill-opacity, 1e-6);

// Update the links…
var link = svg.selectAll(path.link)
.data(links, function(d) { return d.target.id; });

// Enter any new links at the parent's previous position.
link.enter().insert(path, g)
.attr(class, link)
.attr(d, function(d) {
var o = {x: source.x0, y: source.y0};
return diagonal({source: o, target: o});
});

// Transition links to their new position.
link.transition()
.duration(duration)
.attr(d, diagonal);

// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr(d, function(d) {
var o = {x: source.x, y: source.y};
return diagonal({source: o, target: o});
})
.remove();

// Stash the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}

// Toggle children on click.
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}

</script>




[#66144] Wednesday, June 17, 2015, 9 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
kamryn

Total Points: 645
Total Questions: 100
Total Answers: 118

Location: Tanzania
Member since Wed, Feb 24, 2021
3 Years ago
;