Tree Chart

treeChart.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <link href="../../css/common/bootstrap.min.css" rel="stylesheet" type="text/css" />

    <style>
        #buttons > div {
            /*text-align is used to center the div? That's outrageous.*/
            text-align: center;
        }

        #buttons {
            margin-top: 1rem;
            margin-bottom: 1rem;
            min-height: 4rem;
        }
    </style>
    <!--<link href="../../css/d3/d3Test15.css" rel="stylesheet" type="text/css" />-->
</head>
<body>

<div class="container">

    <div class="row">
        <svg style="width: 100%; height: 600px; border: 1px lightgray solid;"></svg>
    </div>

    <div class="row">
        <div class="alert alert-success" role="alert">
            <h4 class="alert-heading">Well done!</h4>
            <p>Aww yeah, you successfully read this important alert message. This example text is going to run a bit longer so that you can see how spacing within an alert works with this kind of content.</p>
            <hr>
            <p class="mb-0">Whenever you need to, be sure to use margin utilities to keep things nice and tidy.</p>
        </div>
    </div>

    <div class="row justify-content-sm-center align-items-end" id="buttons">
        <div class="col-sm">
            <button type="button" class="btn btn-primary" id="primary">Primary</button>
        </div>
        <div class="col-sm">
            <button type="button" class="btn btn-secondary" id="secondary">Secondary</button>
        </div>
        <div class="col-sm">
            <button type="button" class="btn btn-success">Success</button>
        </div>
        <div class="col-sm">
            <button type="button" class="btn btn-danger">Danger</button>
        </div>
        <div class="col-sm">
            <button type="button" class="btn btn-warning">Warning</button>
        </div>
        <div class="col-sm">
            <button type="button" class="btn btn-info">Info</button>
        </div>
        <div class="col-sm">
            <button type="button" class="btn btn-light">Light</button>
        </div>
        <div class="col-sm">
            <button type="button" class="btn btn-dark">Dark</button>
        </div>
        <div class="col-sm">
            <button type="button" class="btn btn-link">Link</button>
        </div>
    </div>

</div>

<script charset="UTF-8" src="../../js/common/jquery-3.3.1.min.js"></script>
<script charset="UTF-8" src="../../js/common/popper.min.js"></script>
<script charset="UTF-8" src="../../js/common/bootstrap.min.js"></script>
<!--https://d3js.org/d3.v4.min.js-->
<script charset="UTF-8" src="../../js/common/d3.v4.min.js"></script>
<!--http://d3js.org/colorbrewer.v1.min.js-->
<script charset="UTF-8" src="../../js/common/colorbrewer.v1.min.js"></script>
<!--https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.25.6/d3-legend.min.js-->
<script src="../../js/common/d3-legend.min.js"></script>
<!--<script src="../../js/common/d3.layout.cloud.min.js"></script>-->
<script src="../../js/common/d3.layout.cloud.min.js"></script>
<script charset="UTF-8" src="../../js/d3/treeChart.js"></script>
</body>
</html>

goddess.csv:

name,city,sexDrive
Angelina Jolie,Los Angeles,70
Angelina Jolie,Malibu,30
Angelina Jolie,Malibu,40
Angelina Jolie,Malibu,50
Angelina Jolie,Malibu,80
Scarlett Johansson,Los Angeles,80
Gal Gadot,Jerusalem,95
Gal Gadot,San Francisco,23
Gal Gadot,West Covina,50
Emma Watson,London,70
Emma Watson,Paris,60
Kat Dennings,Pennsylvania,85
Emilia Clarke,London,45
Anne Hathaway,Brooklyn,35
Rachel McAdams,London,63

treeChart.js:

$(function () {

    d3.csv("../../csv/d3/goddess.csv", goddessData => {

        //Hierarchical data (filter after filter, first group by name, then group by city)
        const nestedDataset = d3.nest()
            .key(d => d.name)
            .key(d => d.city)
            .entries(goddessData);

        console.log(nestedDataset);

        //Puts the array that d3.nest creates inside a "root" object that acts as the top-level parent
        const packableDataset = {"id": "All Goddesses", "values": nestedDataset};

        //Process the hierarchy with an accessor function for child elements to look for values, which matches the data created by d3.nest
        const root = d3.hierarchy(packableDataset, d => d.values)
            //Determine the size of leaf nodes
            .sum(d => parseInt(d["sexDrive"]));

        console.log("root", root);

        const treeChart = d3.tree().size([500, 500]);

        const treeData = treeChart(root).descendants();

        console.log("treeData", treeData);

        const depthScale = d3.scaleOrdinal().range(colorbrewer.Spectral["4"]);

        const nodeG = d3.select("svg")
            .append("g")
            .attr("id", "treeG")
            .attr("transform", "translate(60, 20)")
            .selectAll("g")
            .data(treeData)
            .enter()
            .append("g")
            .attr("class", "node")
            //Draw a <g> element for each node so we can put a circle in it now and add a label later
            // .attr("transform", d => `translate(${d.x}, ${d.y})`);
            //Position horizontally
            .attr("transform", d => `translate(${d.y}, ${d.x})`);

        nodeG.append("circle")
            .attr("r", 10)
            //Fill based on the depth calculated by d3.hierarchy
            .style("fill", d => depthScale(d.depth))
            .style("stroke", "white")
            //Add a white halo around each node to give the connecting lines an offset appearance
            .style("stroke-width", "2px");

        nodeG.append("text")
            .style("text-anchor", "middle")
            .style("fill", "#4f442b")
            //id for the root node, key for .nest() results, sexDrive for the leafNodes
            .text(d => d.data.id || d.data.key || d.data.sexDrive);

        d3.select("#treeG")
            .selectAll("line")
            //Draw links using the same data except filter out any nodes that don’t have parents (which won’t have links)
            .data(treeData.filter(d => d.parent))
            .enter()
            .insert("line", "g")
            // //Draw the link starting at the parent node location
            // .attr("x1", d => d.parent.x)
            // .attr("y1", d => d.parent.y)
            // //Draw the link ending at the child node location
            // .attr("x2", d => d.x)
            // .attr("y2", d => d.y)
            //Position horizontally
            //Draw the link starting at the parent node location
            .attr("x1", d => d.parent.y)
            .attr("y1", d => d.parent.x)
            //Draw the link ending at the child node location
            .attr("x2", d => d.y)
            .attr("y2", d => d.x)
            .style("stroke", "black");


        //The following block of code enables you to pan the svg
        //Creates a new zoom component
        const treeZoom = d3.zoom();
        //Keys the "zoom" event to the zoomed() function
        treeZoom.on("zoom", () => {
            d3.select("#treeG")
                //Updating the <g> to set it to the same translate setting of the zoom component updates the position of the <g> and all its child elements
                .attr("transform", `translate(${d3.event.transform.x}, ${d3.event.transform.y})`);
        });
        //Calls our zoom component with the SVG canvas
        d3.select("svg").call(treeZoom);


    });

});

Effect:

猜你喜欢

转载自blog.csdn.net/qq_25527791/article/details/86772099
今日推荐