1

我是 D3 api 的新手。我必须制作一个树状结构,它有一个 json 文件,其中的值是硬编码的,我有一个 servlet,我从数据库中获取一些值,我必须在其中动态地制作 json servlet 并且必须将响应设置回 D3。这是我编写 d3 的 html。我可以使用 java 类创建 json,但不能从 D3.js 调用它,这是我的 java 文件和创建的 json 以及我的 html 文件.....

public class Test {

public static void main(String[] args) 
{
    // hierarchical data in a flattened list
    String[][] data = {
            {"Toyota", "Gas", "Compact", "Corolla"},
            {"Toyota", "Gas", "Compact", "Camry"},
            {"Toyota", "Hybrid", "Compact", "Prius"},
            {"Honda", "Gas", "Compact", "Civic"}
    };

    TreeManager treeManager = new TreeManager();

    for(String[] row : data)
    {
        // build the path to our items in the tree
        List<String> path = new ArrayList<String>();
        for(String item : row)
        {
            // add this item to our path
            path.add(item);
            // will add it unless an Item with this name already exists at this path
            treeManager.addData(treeManager, path);
        }
    }

    treeManager.getData(data[0]).putValue("MPG", 38);
    treeManager.getData(data[1]).putValue("MPG", 28);

    Gson gson = new Gson();

    System.out.println(gson.toJson(treeManager));
}

/**
 * This base class provides the hierarchical property of
 * an object that contains a Map of child objects of the same type.
 * It also has a field - Name
 *
 */
public static abstract class TreeItem implements Iterable<TreeItem>{

    private Map<String, TreeItem> children;     
    private String name;

    public TreeItem() {
        children = new HashMap<String, TreeItem>();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void addChild(String key, TreeItem data) 
    {           
        children.put(key, data);
    }

    public TreeItem getChild(String key) 
    {           
        return children.get(key);
    }

    public boolean hasChild(String key) 
    {           
        return children.containsKey(key);
    }

    @Override
    public Iterator<TreeItem> iterator() {          
        return children.values().iterator();
    }           
}

/**
 * This is our special case, root node. It is a TreeItem in itself
 * but contains methods for building and retrieving items from our tree
 *
 */
public static class TreeManager extends TreeItem
{       
    /**
     * Will add an Item to the tree at the specified path with the value
     * equal to the last item in the path, unless that Item already exists 
     */
    public void addData(List<String> path)
    {
        addData(this, path);
    }

    private void addData(TreeItem parent, List<String> path)
    {
        // if we're at the end of the path - create a node
        String data = path.get(0);
        if(path.size() == 1)
        {
            // unless there is already a node with this name
            if(!parent.hasChild(data))
            {
                Group group = new Group();
                group.setName(data);
                parent.addChild(data, group);
            }
        }
        else
        {
            // pass the tail of this path down to the next level in the hierarchy
            addData(parent.getChild(data), path.subList(1, path.size()));
        }
    }

    public Group getData(String[] path)
    {
        return (Group) getData(this, Arrays.asList(path));
    }

    public Group getData(List<String> path)
    {
        return (Group) getData(this, path);
    }

    private TreeItem getData(TreeItem parent, List<String> path)
    {
        if(parent == null || path.size() == 0)
        {
            throw new IllegalArgumentException("Invalid path specified in getData, remainder: " 
                    + Arrays.toString(path.toArray()));
        }
        String data = path.get(0);
        if(path.size() == 1)
        {
            return parent.getChild(data);
        }
        else
        {
            // pass the tail of this path down to the next level in the hierarchy
            return getData(parent.getChild(data), path.subList(1, path.size()));
        }
    }
}

public static class Group extends TreeItem {

    private Map<String, Object> properties;

    public Object getValue(Object key) {
        return properties.get(key);
    }

    public Object putValue(String key, Object value) {
        return properties.put(key, value);
    }

    public Group () {
        super();
        properties = new HashMap<String, Object>();
       }       
   }


}

这是我们的json

   {
"children": {
    "Toyota": {
        "properties": {},
        "children": {
            "Hybrid": {
                "properties": {},
                "children": {
                    "Compact": {
                        "properties": {},
                        "children": {
                            "Prius": {
                                "properties": {},
                                "children": {},
                                "name": "Prius"
                            }
                        },
                        "name": "Compact"
                    }
                },
                "name": "Hybrid"
            },
            "Gas": {
                "properties": {},
                "children": {
                    "Compact": {
                        "properties": {},
                        "children": {
                            "Corolla": {
                                "properties": {
                                    "MPG": 38
                                },
                                "children": {},
                                "name": "Corolla"
                            },
                            "Camry": {
                                "properties": {
                                    "MPG": 28
                                },
                                "children": {},
                                "name": "Camry"
                            }
                        },
                        "name": "Compact"
                    }
                },
                "name": "Gas"
            }
        },
        "name": "Toyota"
    },
    "Honda": {
        "properties": {},
        "children": {
            "Gas": {
                "properties": {},
                "children": {
                    "Compact": {
                        "properties": {},
                        "children": {
                            "Civic": {
                                "properties": {},
                                "children": {},
                                "name": "Civic"
                            }
                        },
                        "name": "Compact"
                    }
                },
                "name": "Gas"
            }
        },
        "name": "Honda"
           }
         }
     }

这是我的html文件...

<meta charset="utf-8">

.node circle {
    cursor: pointer;
    stroke: #3182bd;
    stroke-width: 1.5px;
}

.node text {
    font: 10px sans-serif;
    pointer-events: none;
    text-anchor: middle;
}

line.link {
    fill: none;
    stroke: #9ecae1;
    stroke-width: 1.5px;
}

<script type="text/javascript" src="d3/d3.v3.min.js"></script>
<script>

    var width = 960,
    height = 500,
    root;

    var force = d3.layout.force()
    .linkDistance(80)
    .charge(-120)
    .gravity(.04)
    .size([width, height])
    .on("tick", tick);

    //adding as svg element
    var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

    var link = svg.selectAll(".link"),
    node = svg.selectAll(".node");

d3.json("graph.json", function(error, json) {
        root = json;
        update(); //responsible for creating the layout
    });

    function update() {
        var nodes = flatten(root),

        /*
         *d3.layout.tree() is the starting point 
         *for tree layouts in D3. 
         *The call to this function returns an object
         * that contains a bunch of methods to configure 
         * the layout and also provides methods to 
         * compute the layout
         **/           

        links = d3.layout.tree().links(nodes);//attach the nodes

        // Restart the force layout.
        force
        .nodes(nodes)
        .links(links)
        .start();

        // Update links.
        link = link.data(links, function(d) { return d.target.id; });

        link.exit().remove();

        link.enter().insert("line", ".node")
        .attr("class", "link");

        // Update nodes.
        node = node.data(nodes, function(d) { return d.id; });

        node.exit().remove();

        var nodeEnter = node.enter().append("g")
        .attr("class", "node")
        .on("click", click)
        .call(force.drag);

        nodeEnter.append("circle")
        .attr("r", function(d) { return Math.sqrt(d.size) / 10 || 4.5; });

        nodeEnter.append("text")
        .attr("dy", ".35em")
        .text(function(d) { return d.name; });

        node.select("circle")
        .style("fill", color);
    }


    /*Giving elements on click*/
    function tick() {
        link.attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });

        node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
    }


    /*Adjusting the color of each node*/
    function color(d) {
        return d._children ? "#3182bd" // collapsed package
        : d.children ? "#c6dbef" // expanded package
        : "#fd8d3c"; // leaf node
    }

    // Toggle children on click.
    function click(d) {
        if (d3.event.defaultPrevented) return; // ignore drag
        if (d.children) {
            d._children = d.children;
            d.children = null;
        } else {
            d.children = d._children;
            d._children = null;
        }
        update();
    }

    // Returns a list of all nodes under the root.
    function flatten(root) {
        var nodes = [], i = 0;

        function recurse(node) {
            if (node.children) node.children.forEach(recurse);
            if (!node.id) node.id = ++i;
            nodes.push(node);
        }

        recurse(root);
        return nodes;
    }

</script>

这是 json 和 html 文件,现在我必须动态地制作 json 并将响应设置回 D3 api。请帮助...

4

1 回答 1

0

此代码使用 AJAX 请求从您的服务器检索 JSON 文件:

d3.json("graph.json", function(error, json) {
    root = json;
    update(); //responsible for creating the layout
});

现在,您使用的 URL 将简单地从与服务器上的 HTML 文件相同的位置获取一个名为“graph.json”的静态文件。您可以将此 URL 更改为doGet在您的 servlet 中调用的 URL,然后doGet返回您想要的动态 JSON。

于 2013-10-25T04:24:05.350 回答