如何绘制图形内部节点?

时间:2015-07-14 16:46:58

标签: d3.js

我可以使用d3绘制饼图或图形,我甚至可以在图形的每个节点内绘制一个饼图,如图here所示。

是否可以创建一个可重复使用的函数来生成饼图并将其结果附加到每个节点?这样,饼图代码可以重复使用,例如在图表库中。

    var node = svg.selectAll(".node")
    .data(graph.nodes)
    .enter().append("g")
    .attr("class", "node");

    // draw pie chart
    node.selectAll("path")
    .data(function(d, i) {return pie(d.proportions); })
    .enter()
    .append("svg:path")
    .attr("d", arc)
    .attr("fill", function(d, i) { return color(d.data.group); });;

从上面的代码中,我尝试了以下不起作用的代码

    var node = svg.selectAll(".node")
    .data(graph.nodes)
    .enter().append("g")
    .attr("class", "node")
    .call(drawPie(function(d) { return d.proportions; }));

     function drawPie(d) {
        this.selectAll("path")
        .data(function(d, i) {return pie(d.proportions); })
        .enter()
        .append("svg:path")
        .attr("d", arc)
        .attr("fill", function(d, i) { return color(d.data.group); });;
     }

3 个答案:

答案 0 :(得分:1)

您最初的想法比其他答案中推荐的想法更接近,您只需要了解selection.call的工作原理。

这没有经过测试,但一般原则就像......

var node = svg.selectAll(".node")
.data(graph.nodes)
.enter().append("g")
.attr("class", "node")
.call(drawPie);

 function drawPie(selection) {
    this.selectAll("path")
    .data(function(d, i) {return pie(d.proportions); })
    .enter()
    .append("svg:path")
    .attr("d", arc)
    .attr("fill", function(d, i) { return color(d.data.group); });;
 }  

关于你的第一次尝试,如果你停下来思考这条线......

.call(drawPie(function(d) { return d.proportions; }));  

...它实际上是在尝试调用null,因为这是drawPie返回的内容。它相当于......

.call(null);

答案 1 :(得分:0)

根据建议,这里是修改后的代码,仍然需要一些改进。错误消息报告“第93行未定义不是评估d.proportions的对象”

        graph = { "nodes":[
                           {"proportions": [{"group": 1, "value": 1},
                                            {"group": 2, "value": 2},
                                            {"group": 3, "value": 3}]},
                           {"proportions": [{"group": 1, "value": 2},
                                            {"group": 2, "value": 2},
                                            {"group": 3, "value": 2}]}],
                                            "links":[{"source": 0, "target": 1, "length": 500, "width": 1}]
        }

    var width = 960,
    height = 500,
    radius = 25,
    color = d3.scale.category10();

    var pie = d3.layout.pie()
    .sort(null)
    .value(function(d) { return d.value; });

    var arc = d3.svg.arc()
    .outerRadius(radius)
    .innerRadius(10);

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

    var force = d3.layout.force()
    .charge(-120)
    .linkDistance(4 * radius)
    .size([width, height]);

    force.nodes(graph.nodes)
    .links(graph.links)
    .start();

    var link = svg.selectAll(".link")
    .data(graph.links)
    .enter().append("line")
    .attr("class", "link");

    var node = svg.selectAll(".node")
    .data(graph.nodes)
    .enter()
    .append(function(d) {return createPie(d);}) // .append(createPie)  --- shorter version
    .attr("class", "node");

    // node.selectAll("path")
    // .data(function(d, i) {return pie(d.proportions); })
    // .enter()
    // .append("svg:path")
    // .attr("d", arc)
    // .attr("fill", function(d, i) { return color(d.data.group); });;

    force.on("tick", function() {
             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("x", function(d) { return d.x; })
             .attr("y", function(d) { return d.y; })
             .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"});
             });

    function createPie(d) {
        console.log(d);
            var pie = d3.select(document.createElement('svg:g'));
            pie.selectAll('path')
                .data(function(d, i) {return pie(d.proportions); })
                .enter()
                .append("svg:path")
                .attr("d", arc)
                .attr("fill", function(d, i) { return color(d.data.group); });
            return pie.node();
     }

答案 2 :(得分:-1)

 var node = svg.selectAll(".node")
    .data(graph.nodes)
    .enter()
    .append(function(d){return createPie(d);}) // .append(createPie)  --- shorter version
    .attr("class", "node");


function createPie(data) {
    var pie = d3.select(document.createElement('svg:g'));

    pie.selectAll('path')
    ...;

    return pie.node();
}

更新:

function createPie(d) {
    console.log(d);
        var p = d3.select(document.createElement('svg:g'));
        p.selectAll('path')
            .data(pie(d.proportions))
            .enter()
            .append("svg:path")
            .attr("d", arc)
            .attr("fill", function(d, i) { return color(d.data.group); });
        return p.node();
 }

以前的变量饼需要重构,因为它会覆盖父范围中的那个。

并且数据调用也需要修复