D3JS animation with dynamic HTML content in Angularjs2 / Typescript

I am trying to convert a D3JS tree animation to AngularJS2 / Typescript. I am not a typescript expert.

Creating a basic tree animation is up and running. Now the HTML content needs to be entered into the Tree Nodes.Its Something like the Wizard form, and when and when they click the "Finish" and "Close" buttons, respectively, the active node should be collapsed, and the next node of the tree should be turned on.

The work panel 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 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 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 previous position.
        // Enter any new links at the parent 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 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 + ")");
    }
}

The expected result as an image: Example

If someone can help me with this, it will be really great help!

+4

Source: https://habr.com/ru/post/1663933/


All Articles