class Tree {
constructor(json) {
this.nodes = []
for (const [index, item] of json.entries()) {
var new_node = new Node(item.name, item.parent);
if (index !== 0) {
new_node.parentNode = this.nodes[index - 1]
}
this.nodes.push(new_node);
}
for (var node of this.nodes) {
var node_name = node.name;
node.children = this.nodes.filter(node => node.parentName === node_name);
}
}
buildLayout() {
this.assignLevelAndPosition(this.nodes[0], 0, 0);
return this;
}
assignLevelAndPosition(node, level, position) {
node.level = level
level += 1
node.position = position
if (node.children.length === 0) {
position += 1
} else {
for (var child of node.children) {
child.parentNode = node
position = this.assignLevelAndPosition(child, level, position)
}
}
return position
}
render() {
var svg = d3.create('svg')
.attr('width', 700)
.attr('height', 700);
const posScale = d3.scaleLinear()
.domain([0, 4])
.range([0, 300])
const levelScale = d3.scaleLinear()
.domain([0, 8])
.range([0, 800])
svg.selectAll('line')
.data(this.nodes)
.join("line")
.attr('transform', row => `translate(200,100)`)
.attr("x1", d => levelScale(d.parentNode === null ? 0 : d.parentNode.level))
.attr("y1", d => posScale(d.parentNode === null ? 0 : d.parentNode.position))
.attr("x2", d => levelScale(d.level))
.attr("y2", d => posScale(d.position));
const g = svg.selectAll('g')
.data(this.nodes)
.join('g')
.attr('transform', row => `translate(200, 100)`);
const node_radius = 35
g.classed("nodeGroup", true).append('circle')
.attr('cx', node => levelScale(node.level))
.attr('cy', node => posScale(node.position))
.attr('r', node_radius)
.attr("text", node => node.name);
g.classed("label", true).append('text')
.attr('x', node => levelScale(node.level))
.attr('y', node => posScale(node.position))
.text(node => node.name)
return svg.node();
}
}