带图例的D3区域地图。

7
我有一个美国人口密度分布图,我想在地图上添加一个图例,显示量化范围的值。我看到过其他类似主题的问题,但似乎无法让它在我的特定情况下工作。我知道我需要包括颜色范围或颜色域,但不确定这是否是正确的方法。目前只有一个要素显示在图例中,可能所有的图例要素都堆叠在一起了。如何确认并如何修复呢?
//Define default colorbrewer scheme
var colorSchemeSelect = "Greens";
var colorScheme = colorbrewer[colorSchemeSelect]; 

//define default number of quantiles
var quantiles = 5;

//Define quantile scale to sort data values into buckets of color
var color = d3.scale.quantile()
   .range(colorScheme[quantiles]);

d3.csv(data, function (data) {
    color.domain([
         d3.min(data, function (d) {
           return d.value;
         }),
         d3.max(data, function (d
           return d.value
         }) 
    ]);

//legend                            
var legend = svg.selectAll('rect')
    .data(color.domain().reverse())
    .enter()
    .append('rect')
    .attr("x", width - 780)
    .attr("y", function(d, i) {
       return i * 20;
    })
   .attr("width", 10)
   .attr("height", 10)
   .style("fill", color);

类似于这个的东西?你只需要将输出颜色范围设置为分位数(即5种颜色)。 - Lars Kotthoff
是的,我希望它与那个示例类似。但我不想像示例那样使用硬编码值的变量来表示图例。我希望使用color.domain和colorScheme变量来填充图例值。 - bailey
1个回答

12
您正在使用的图例代码在使用序数比例尺时可以完美运行,其中域由与颜色范围一一对应的离散值组成。但是您正在使用分位比例尺,因此需要不同的方法。
对于d3分位比例尺,域是所有可能的输入值列表,而范围是离散输出值列表。该域列表按升序排序,然后分为大小相等的组,并将每个输出值从范围中分配给它们。组数由输出值的数量确定。
考虑到这一点,为了获得每种颜色的一个图例条目,您需要使用颜色比例尺的范围而不是域作为图例的数据。然后,您可以使用quantileScale.invertExtent()方法找到绘制该颜色的最小和最大输入值。

演示代码,将每个图例条目制作为包含彩色矩形和显示相应值的文本标签的<g>元素。

var legend = svg.selectAll('g.legendEntry')
    .data(color.range().reverse())
    .enter()
    .append('g').attr('class', 'legendEntry');

legend
    .append('rect')
    .attr("x", width - 780)
    .attr("y", function(d, i) {
       return i * 20;
    })
   .attr("width", 10)
   .attr("height", 10)
   .style("stroke", "black")
   .style("stroke-width", 1)
   .style("fill", function(d){return d;}); 
       //the data objects are the fill colors

legend
    .append('text')
    .attr("x", width - 765) //leave 5 pixel space after the <rect>
    .attr("y", function(d, i) {
       return i * 20;
    })
    .attr("dy", "0.8em") //place text one line *below* the x,y point
    .text(function(d,i) {
        var extent = color.invertExtent(d);
        //extent will be a two-element array, format it however you want:
        var format = d3.format("0.2f");
        return format(+extent[0]) + " - " + format(+extent[1]);
    });

2
顺便说一下,看了你代码的其余部分,似乎你真正想使用的是d3 quantize scale(而不是quantile),它的域是一个[min,max]范围,该比例将其分成代表域变量等大小范围的组(而不是相等数量的观测)。上面的图例代码对于任何类型的比例尺都适用,因为在两种情况下,组数由范围数组确定,并且可以使用invertExtent访问相应的域值。 - AmeliaBR
非常感谢您周到的回答!我希望我能为您的答案点赞,但我还没有足够的声望。我只是在使用示例代码中的.invertExtent()方法时遇到了问题。它在控制台中给出了一个错误,并且没有显示与图例相关联的文本。 - bailey
你是否正在使用最新版本的d3?根据这个链接invertExtent方法似乎只在3.2版本中为quantize和threshold比例尺添加了。使用最新版本:这里是一个使用quantize比例尺的实时版本;以及这里是一个使用quantile比例尺的实时版本。我对格式化函数和文本对齐进行了一些整理修改(我将更新上面的示例代码),但这两个问题都不会导致错误。 - AmeliaBR
invertExtent 方法是在 quantile scales in 3.2.4 中添加的,最新版本来自 d3js.org 的版本是 3.4.2。 - AmeliaBR
我没有使用最新版本,所以问题得到了解决!谢谢!你听说过最新版本的D3在地图投影方面出现问题吗? - bailey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接