使用d3.js在地图点上的饼图

时间:2017-01-31 04:25:34

标签: d3.js

我想为地图上的每个点绘制一个饼图,而不是圆圈。 地图和点显示良好,但饼图未显示在地图点上。也没有错误。我也可以在地图中看到添加的饼图代码。

以下是代码段。

var w = 600;
var h = 600;
var bounds = [[78,30], [87, 8]];  // rough extents of India
var proj = d3.geo.mercator()
        .scale(800)
        .translate([w/2,h/2])
        .rotate([(bounds[0][0] + bounds[1][0]) / -2,
            (bounds[0][1] + bounds[1][1]) / -2]); // rotate the project to bring India into view.

var path = d3.geo.path().projection(proj);

var map = d3.select("#chart").append("svg:svg")
        .attr("width", w)
        .attr("height", h);

var india = map.append("svg:g")
        .attr("id", "india");

var gDataPoints = map.append("g"); // appended second
d3.json("data/states.json", function(json) {
    india.selectAll("path")
            .data(json.features)
            .enter().append("path")
            .attr("d", path);

});

d3.csv("data/water.csv", function(csv) {
    console.log(JSON.stringify(csv))
    gDataPoints.selectAll("circle")
            .data(csv)
            .enter()
            .append("circle")
            .attr("id", function (d,i) {
                return "chart"+i;
            })
            .attr("cx", function (d) {
                return proj([d.lon, d.lat])[0];
            })
            .attr("cy", function (d) {
                return proj([d.lon, d.lat])[1];
            })
            .attr("r", function (d) {
                return 3;
            })
            .each(function (d,i) {
                barchart("chart"+i);
            })
            .style("fill", "red")
            //.style("opacity", 1);
});


function barchart(id){

    var data=[15,30,35,20];      
    var radius=30;
    var color=d3.scale.category10()        

    var svg1=d3.select("#"+id)
            .append("svg").attr('width',100).attr('height',100);

    var group=svg1.append('g').attr("transform","translate(" + radius + "," + radius + ")");
    var arc=d3.svg.arc()
            .innerRadius('0')
            .outerRadius(radius);
    var pie=d3.layout.pie()
            .value(function(d){
                return d;
            });

    var arcs=group.selectAll(".arc")
            .data(pie(data))
            .enter()
            .append('g')
            .attr('class','arc')

    arcs.append('path')
            .attr('d',arc)
            .attr("fill",function(d,i){
                return color(d.data);
                //return colors[i]
            });
}

water.csv:

lon,lat,quality,complaints
80.06,20.07,4,17
72.822,18.968,2,62
77.216,28.613,5,49
92.79,87.208,4,3
87.208,21.813,1,12
77.589,12.987,2,54
16.320,75.724,4,7

1 个答案:

答案 0 :(得分:2)

在测试代码时,我根本无法看到饼图渲染。但是,我相信我仍然有一个解决方案。

您不需要单独的饼图功能来调用每个点。我确信对此有各种各样的意见,但是关于Stack Overflow的d3问题通常会调用额外的功能来延长代码,同时充分利用d3的优势和内置功能。<​​/ p>

为什么我会在这种情况下有这种感觉?很难保留绑定到svg对象的数据与饼图函数之间的链接,这就是为什么你必须将点的id传递给你的函数。如果您想在csv中拥有饼图数据,这将更加复杂。

使用d3的数据绑定和选择,您可以使用更简单的代码完成所需的一切。我花了一些时间来了解如何做到这一点,但它确实让你的生活变得更轻松。

注意:我道歉,我移植了您发布到d3v4的代码,但我已经包含了下面d3v3代码的链接,以及d3v4,尽管在片段中只有明显的变化可能是从颜色(i)到颜色[i]

在这种情况下,我们可以添加一个circle元素,然后将元素直接附加到每个selection.each(),而不是调用函数将饼图附加到每个g元素。 {1}}选择。

另外,为了让生活更轻松,如果我们最初为每个g元素添加一个变换,我们可以使用相对测量来在每个g中放置项目,而不是找出我们的绝对svg坐标否则就需要了。

g

现在,如果我们想要显示每个饼图的csv数据,并且可能添加标签,该怎么办?现在很容易做到这一点。在csv中,如果有一个标记为 d3.csv("water.csv", function(error, water) { // Append one g element for each row in the csv and bind data to it: var points = gDataPoints.selectAll("g") .data(water) .enter() .append("g") .attr("transform",function(d) { return "translate("+projection([d.lon,d.lat])+")" }) .attr("id", function (d,i) { return "chart"+i; }) .append("g").attr("class","pies"); // Add a circle to it if needed points.append("circle") .attr("r", 3) .style("fill", "red"); // Select each g element we created, and fill it with pie chart: var pies = points.selectAll(".pies") .data(pie([0,15,30,35,20])) .enter() .append('g') .attr('class','arc'); pies.append("path") .attr('d',arc) .attr("fill",function(d,i){ return color[i]; }); }); 的列,其中的值由短划线和名为data的列分隔,我们可以轻松调整代码以显示此新数据:

label

我们想要显示的数据已经绑定到我们为csv中的每一行创建的初始d3.csv("water.csv", function(error, water) { var points = gDataPoints.selectAll("g") .data(water) .enter() .append("g") .attr("transform",function(d) { return "translate("+projection([d.lon,d.lat])+")" }) .attr("class","pies") points.append("text") .attr("y", -radius - 5) .text(function(d) { return d.label }) .style('text-anchor','middle'); var pies = points.selectAll(".pies") .data(function(d) { return pie(d.data.split(['-'])); }) .enter() .append('g') .attr('class','arc'); pies.append("path") .attr('d',arc) .attr("fill",function(d,i){ return color[i]; }); }); 。现在我们要做的就是附加我们想要显示的元素,并选择我们想要显示的绑定数据的属性。

这种情况下的结果如下:

enter image description here

我在v3和v4中发布了一些示例,以显示遵循上述饼图方法的潜在实现:

为所有饼图提供一个静态数据数组,如示例所示:v4v3

通过从csv中提取数据来显示:v4v3