将时间轴放在D3.js树图上

时间:2017-09-05 10:24:34

标签: javascript d3.js

我是D3.js的新手,所以这可能是一个简单的问题。我有一个简单的D3树图,在我的treeData json中,每个节点都有一个“日期”组件。如何粘合树形图下方的时间线,以便每个节点对应于时间轴中的日期?

以下是完整的代码。我试图找到一个有效的类似例子,找不到任何东西。在这里找到一个例子,但它不起作用: d3.js - Having a tree layout, how to change the X-axis to use a time scale in D3?

var treeData = [{
    "name": "Top Level",
    "date": "12-Jan-15",
    "parent": "null",
    "children": [{
        "name": "Level 2: A",
        "date": "13-Mar-16",
        "parent": "Top Level",
        "children": [{
            "name": "Son of A",
            "date": "1-Aug-16",
            "parent": "Level 2: A"
        }, {
            "name": "Daughter of A",
            "date": "5-Sep-16",
            "parent": "Level 2: A"
        }]
    }, {
        "name": "Level 2: B",
        "date": "12-Jan-17",
        "parent": "Top Level"
    }]
}];

// ************** Generate the tree diagram  *****************
var margin = {
        top: 20,
        right: 120,
        bottom: 20,
        left: 120
    },
    width = 960 - margin.right - margin.left,
    height = 500 - margin.top - margin.bottom;

var i = 0;

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("#tree").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 + ")");

root = treeData[0];

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;
    });

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

    // Enter the nodes.
    var nodeEnter = node.enter().append("g")
        .attr("class", "node")
        .attr("transform", function(d) {
            return "translate(" + d.y + "," + d.x + ")";
        });

    nodeEnter.append("circle")
        .attr("r", 10)
        .style("fill", "#fff");

    nodeEnter.append("text")
        .attr("x", function(d) {
            return d.children || d._children ? -13 : 13;
        })
        .attr("dy", ".35em")
        .attr("text-anchor", function(d) {
            return d.children || d._children ? "end" : "start";
        })
        .text(function(d) {
            return d.name;
        })
        .style("fill-opacity", 1);

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

    // Enter the links.
    link.enter().insert("path", "g")
        .attr("class", "link")
        .attr("d", diagonal);

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

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

.link {
    fill: none;
    stroke: #ccc;
    stroke-width: 2px;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<div id="tree">

</div>
<div id="time">

</div>

1 个答案:

答案 0 :(得分:0)

这是在为D3树图创建时间轴时可以使用的答案。代码有注释,应该清楚它的作用。保存为.html,它应该在浏览器中工作。

    <!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <title>Simple Tree Example</title>

    <style>
        .node circle {
            fill: steelblue;
            stroke: grey;
            stroke-width: 3px;
        }

        .node text {
            font: 12px sans-serif;
        }
        /* link is for the lines */

        .link {
            fill: none;
            stroke: #ccc;
            stroke-width: 2px;
            z-index: -1;
        }
        .axis path,
        .axis line {
          fill: none;
          stroke: slategray;
          shape-rendering: crispEdges;
        }
        .x.axis line,
        .x.axis path {
          fill: none;
          stroke: #000;
        }
    </style>
</head>

<body>
    </div>
    <!-- load the d3.js library -->
    <script src="http://d3js.org/d3.v3.min.js"></script>

    <script>
        var treeData = [{
            "name": "Root",
            "date": "01-01-2017",
            "children": [{
                    "name": "A",
                    "date": "01-02-2017",
                    "children": [

                        {
                            "name": "B",
                            "date": "01-05-2017",
                            "children": [{
                                "name": "C",
                                "date": "01-06-2017",
                                "children": [{
                                    "name": "D",
                                    "date": "01-07-2017",
                                }]
                            }]


                        }
                    ]
                }              
            ]
        }];

        // ************** Generate the tree diagram  *****************
        var margin = {
                top: 20,
                right: 60,
                bottom: 20,
                left: 120
            },
            width = 1000 - margin.right - margin.left,
            height = 200 - margin.top - margin.bottom;

        var i = 0;

        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),
            g = svg.append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        root = treeData[0];
        var nodes = tree.nodes(root).reverse();
        var maxdate = d3.max(nodes, function (d) {
            return new Date(d.date.replace(/(\d{2})-(\d{2})-(\d{4})/, "$1/$2/$3"));
        });
        var mindate = d3.min(nodes, function (d) {
            return new Date(d.date.replace(/(\d{2})-(\d{2})-(\d{4})/, "$1/$2/$3"));
        });

        mindate.setMonth(mindate.getMonth() + 1);
        maxdate.setMonth(maxdate.getMonth() + 1);
        maxdate.setDate(maxdate.getDate() + 5);

        var x = d3.time.scale()
            .domain([mindate, maxdate])
            .range([0, width]);

        var xAxis = d3.svg.axis()
            .orient("bottom")
            .scale(x)
            .ticks(10);
        g.append('g')
            .attr('transform', 'translate(0,' + height + ')') .attr("class", "axis")
            .call(customXAxis);
        var linksg =    g.append("g");

        function customXAxis(g) {
            g.call(xAxis);
            //g.select('.domain').remove();
        };

        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 * 80;
            });

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

            // Enter the nodes.
            var nodeEnter = node.enter().append("g")
                .attr("class", "node")
                .attr("transform", function (d) {
                    var ddate = d.date.split("-");
                    var t = new Date(ddate[2], ddate[0], ddate[1]);
                    return "translate(" + x(t) + "," + d.x + ")";
                });

            nodeEnter.append("circle")
                .attr("r", 15)
                .transition()
                .delay(350)
                .style("fill", "steelblue");


            nodeEnter.append("text")
                .attr("x", function (d) {
                    return d.children || d._children ? -20 : 20;
                })
                .attr("dy", ".35em")
                .attr("text-anchor", function (d) {
                    return d.children || d._children ? "end" : "start";
                })
                .text(function (d) {
                        return d.name
                })
                .style("fill-opacity", 1);


            // Declare the links…
            var link = linksg.selectAll('.link')
                .data(nodes)
                .enter().append('path')
                .attr('class', 'link')
                .attr('d', function (d) {
                    if (d.parent != undefined) {
                        var res = d.date.split("-");
                        var nodeDate = new Date(+res[2], +res[0], +res[1]);
                        var res = d.parent.date.split("-");
                        var parentDate = new Date(+res[2], +res[0], +res[1]);
                        return 'M' + x(nodeDate) + ',' + d.x +
                            'C' + (x(nodeDate) + x(parentDate)) / 2 + ',' + d.x +
                            ' ' + (x(nodeDate) + x(parentDate)) / 2 + ',' + d.parent.x +
                            ' ' + x(parentDate) + ',' + d.parent.x;
                    }
                });
        } // end update () function
    </script>
</body>

</html>.