具有Angularjs2 / Typescript中动态HTML内容的D3JS动画

时间:2016-12-16 08:51:36

标签: javascript angular d3.js svg typescript

我正在尝试将D3JS树动画转换为AngularJS2 / Typescript。 我不是打字稿的专家。

创建基本树动画已完成并正常工作。 现在HTML内容需要在Tree Nodes中注入。它类似于表单向导以及何时"完成"和"关闭"按钮命中,应该折叠活动节点,并且应该启用树的下一个节点。

可在此处找到工作插件: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 + ")");
    }
}

预期输出附加为图像: Example

如果有人可以帮助我,这将是一个很大的帮助!!

0 个答案:

没有答案