I am trying to convert D3JS Tree Animation into AngularJS2/Typescript. I am not an expert of typescript.
Creating the basic tree animation is done and working. Now HTML contents needs to be injected in Tree Nodes.Its Something like form Wizard and as and when "Finish" and "Close" button hit, respectively the active node should be collapsed and the next node of the tree should be enabled.
Working plunk can be found here : https://plnkr.co/edit/cxuzCr?p=preview
export class AppComponent {
name = 'D3!';
public margin = {
top: 20,
right: 120,
bottom: 20,
left: 120
};
width = 1400 - this.margin.right - this.margin.left;
height = 800 - this.margin.top - this.margin.bottom;
public inst: number = 1;
public duration: number = 750;
public rectW: number = 60;
public rectH: number = 30;
public zm: any;
public collapse: Function;
public d: any;
public error: any;
public view: any;
public parent: any;
public visitFn: any;
public childrenFn: any;
public links: any;
public tree: any;
public maxLabelLength: any;
public svg: any;
public drag: any;
public dragmove: any;
// how much horz space to give a flaring of branches (menus, day/night behaviour)
public BRANCH_SPACE = 80;
constructor(private _nodeDataService: NodeDataService) {
}
ngOnInit() {
this.tree = d3.layout.tree().size([this.height, this.width]);
this.drag = d3.behavior.drag()
.on("drag", this.dragmove);
this.dragmove = (d) => {
var x = d3.event.x;
var y = d3.event.y;
d3.select(this).attr("transform", "translate(" + x + "," + y + ")");
};
this.svg = d3.select("#body").append("svg")
.attr("width", this.width + this.margin.right + this.margin.left)
.attr("height", this.height + this.margin.top + this.margin.bottom)
.append("g")
.call(this.drag)
.attr("transform", "translate(" + this.margin.left + "," + this.margin.top + ")");
this.getNodes();
//this.zm.translate([350, 20]);
}
diagonal = d3.svg.diagonal().projection((d: any) => {
// return [d.x + this.rectW / 2, d.y + this.rectH / 2];
return [d.y, d.x];
});
// A recursive helper function for performing some setup by walking through all nodes
public visit = (parent: any, visitFn: any, childrenFn: any): void => {
if (typeof childrenFn !== 'function') {
//default childrenFn =
childrenFn = function (node) {
return node.children || null;
};
}
if (!parent) {
return;
}
visitFn(parent);
var children = childrenFn(parent);
if (children) {
for (var i = 0, count = children.length; i < count; i++) {
this.visit(children[i], visitFn, childrenFn);
}
}
}
getNodes() {
this._nodeDataService.getNodes().subscribe(
// the first argument is a function which runs on success
data => {
this._nodeDataService.root = data;
debugger;
this._nodeDataService.root.x0 = 0;
this._nodeDataService.root.y0 = this.height / 2;
console.log("height", this.height);
this.collapse = (d: any) => {
if (d.children) {
d._children = d.children;
d._children.forEach(this.collapse);
d.children = null;
}
};
this._nodeDataService.root.children.forEach(this.collapse);
this.update(this._nodeDataService.root);
// Call visit function to establish maxLabelLength
this.visit(this._nodeDataService.root, (d: any) => {
let totalNodes: number = 0;
totalNodes++;
this.maxLabelLength = Math.max(d.name.length, this.maxLabelLength);
}, (d: any) => {
return d.children && d.children.length > 0 ? d.children : null;
});
},
// the second argument is a function which runs on error
err => console.error(err),
// the third argument is a function which runs on completion
// () => console.log('done loading Nodes', this._nodeDataService.root)
)
};
//necessary so that zoom knows where to zoom and unzoom from
// zm.translate([350, 20]);
selectFrame = d3.select(self.frameElement).style("height", "800px");
update = (source: any) => {
let i: number = 0;
// Compute the new tree layout.
let nodes = this.tree.nodes(this._nodeDataService.root).reverse(),
links = this.tree.links(nodes);
// Normalize for fixed-depth.
nodes.forEach((n: any) => {
n.y = n.depth * 180;
});
// Update the nodes…
let node = this.svg.selectAll("g.node")
.data(nodes, function (n: any) {
return n.size || (n.id = ++i);
}
);
// Enter any new nodes at the parent's previous position.
let nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", (n: any) => {
return "translate(" + source.y0 + "," + source.x0 + ")";
})
.on("click", this.click);
nodeEnter.append("rect")
.attr("width", this.rectW)
.attr("height", this.rectH)
.attr("stroke", "black")
.attr("stroke-width", 1)
.style("fill", (d) => {
return d._children ? "lightsteelblue" : "#fff";
});
nodeEnter.append("text")
.attr("x", this.rectW / 2)
.attr("y", this.rectH / 2)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text((d: any) => {
return d.name;
});
// Transition nodes to their new position.
let nodeUpdate = node.transition()
.duration(this.duration)
.attr("transform", (d: any) => {
return "translate(" + d.y + "," + d.x + ")";
});
nodeUpdate.select("rect")
.attr("width", this.rectW)
.attr("height", this.rectH)
.attr("stroke", "black")
.attr("stroke-width", 1)
.style("fill", (d: any) => {
return d._children ? "lightsteelblue" : "#fff";
});
nodeUpdate.select("text")
.style("fill-opacity", 1);
// Transition exiting nodes to the parent's new position.
let nodeExit = node.exit().transition()
.duration(this.duration)
.attr("transform", (n: any) => {
return "translate(" + source.y + "," + source.x + ")";
})
.remove();
nodeExit.select("rect")
.attr("width", this.rectW)
.attr("height", this.rectH)
//.attr("width", bbox.getBBox().width)""
//.attr("height", bbox.getBBox().height)
.attr("stroke", "black")
.attr("stroke-width", 1);
nodeExit.select("text");
// Update the links…
var link = this.svg.selectAll("path.link")
.data(links, function (n: any) {
return n.target.id;
});
// Enter any new links at the parent's previous position.
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("x", this.rectW / 2)
.attr("y", this.rectH / 2)
.attr("d", (d) => {
var o = {
x: source.x0,
y: source.y0
};
return this.diagonal({
source: o,
target: o
});
});
// Transition links to their new position.
link.transition()
.duration(this.duration)
.attr("d", this.diagonal);
// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(this.duration)
.attr("d", (n: any) => {
var o = {
x: source.x,
y: source.y
}
return this.diagonal({
source: o,
target: o
});
})
// Stash the old positions for transition.
nodes.forEach((n: any) => {
n.x0 = n.x;
n.y0 = n.y;
});
};
click = (d): void => {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
this.update(d);
};
redraw = (d) => {
this.svg.attr("transform",
"translate(" + d3.event.translate + ")"
+ " scale(" + d3.event.scale + ")");
}
}
Expected output attached as Image:
If anyone can help me out in this, it would be really a great help!!