Javascript 如何创建水平图例?

Javascript 如何创建水平图例?,javascript,d3.js,Javascript,D3.js,在D3.js中,如何创建具有两行的水平图例 这是创建图例的当前JavaScript代码: var legendGroup = svg.append("g") .attr("transform", "translate("+(width-50)+",30)"); var legend = legendGroup.selectAll(".legend") .data(nations.map(d=>d.name)) .enter() .app

在D3.js中,如何创建具有两行的水平图例

这是创建图例的当前JavaScript代码:

var legendGroup = svg.append("g")
    .attr("transform", "translate("+(width-50)+",30)");

  var legend = legendGroup.selectAll(".legend")
    .data(nations.map(d=>d.name))
        .enter()
        .append("g")
        .attr("transform", (d,i)=>"translate(0," + 20*i + ")")

  var legendRects = legend.append("rect")
    .attr("width", 10)
        .attr("height", 10)
        .attr("fill", d=> colorScale(d));

  var legendText = legend.append("text")
    .attr("x", 14)
        .attr("y", 8)
    .text(d=>d);

正如您所说,您发布的代码是一列,因为它将图例的每一部分翻译为最后一个20像素以下的内容:
“translate(0,+20*i+)”
。通过操纵translate语句,如果知道数组中有多少个元素,则可以创建两行图例,即使不知道,也可以指定每行中可以有多少个元素

在以下代码块中,
n
表示一行中应包含多少项,
itemWidth
表示每个图例项宽度的像素值,
itemHeight
表示高度

我不知道您有多少图例项,但您可以将其设置为:

.attr("transform", function(d,i) { return 
               "translate(" + i%n * itemWidth + 
               "," +
               Math.floor(i/n) * itemHeight + ")"; })
这应该是这样的:

var数据=[“A类”、“B类”、“C类”、“D类”、“A类”、“B类”、“C类”、“D类”];
var n=data.length/2;
var itemWidth=80;
var itemHeight=18;
var svg=d3.选择(“svg”);
var color=d3.scale.category10();
var legend=svg.selectAll(“.legend”)
.数据(数据)
.输入()
.附加(“g”)
.attr(“transform”,函数(d,i){return”translate(“+i%n*itemWidth+”,“+Math.floor(i/n)*itemHeight+”);)
.attr(“类别”、“图例”);
var rects=legend.append('rect')
.attr(“宽度”,15)
.attr(“高度”,15)
.attr(“填充”,函数(d,i){返回颜色(i);});
var text=legend.append('text')
.attr(“x”,15)
.attr(“y”,12)
.text(函数(d){return d;})

const legendData=['美国'、'巴西'、'印度'、'中国'、'阿拉伯联合酋长国']//要显示为图例的名称应在此数组中。
const legend=d3.select('svg')
.append('g')
.attr('transform','translate('+(margin.left+margin.right+60)+','+(margin.top-20)+'))
.selectAll('g')
.数据(legendData)
.输入()
.append('g');
图例.append('rect')
.attr('fill',(d,i)=>color(d))//const color=d3.scaleOrdinal(d3.schemeCategory 10);
.attr('height',15)
.attr('宽度',15);
图例.append('text')
.attr('x',18)
.attr('y',10)
.attr('dy','.15em'))
.text((d,i)=>d)
.style('text-anchor','start')
.style('font-size',12);
//现在,在添加组后将其隔开:
常数填充=10;
图例.attr('transform',函数(d,i){
返回“translate”()+(d3.sum(legendData,函数(e,j)){
if(j
这是否有效地创建了一个单独的图例行?@HimmelIt创建了一个列,我可以这么说。因此,现在它是垂直排列的。谢谢,我如何才能将这个图例移到右角?您可以将上面的代码片段与代码的第一行结合起来:
var legendGroup=svg.append(“g”).attr(“transform”,“translate”(+(width-50)+”,30)”。-50将图例从右侧向后拉50个像素(30将图例从顶部向下拉30个像素)。您可能希望使用水平图例将图例向右拉至-50以上,因为这将标记图例的最左侧部分。然后使用
var-legend=legendGroup.selectAll(.legend”)
而不是
var-legend=svg。selectAll(.legend”)
。好的,这是清楚的。那么,您使用哪个参数来控制RAW的数量?如果我想创建3或4个绘图而不是2个,该怎么办?如果你想修改行数,你可以更改每行中显示的项目数,在我的示例中是
n
。如果我处理的是可变长度的数据数组,那么我应该确保我用来确定
n
的方法向下或向上舍入,以便放置是规则的(因为我使用的方法可能会产生一个非整数,这会干扰项目放置)。我对答案进行了编辑,以包含一个包含4行和整个图例移动的示例
const legendData = ['The United States', 'Brazil', 'India', 'China', 'United Arab Emirates']  // The names which you want to appear as legends should be inside this array.

const legend = d3.select('svg')
  .append('g')
  .attr('transform', 'translate(' + (margin.left + margin.right + 60) + ',' + (margin.top - 20) + ')')
  .selectAll('g')
  .data(legendData)
  .enter()
  .append('g');

legend.append('rect')
  .attr('fill', (d, i) => color(d))     //   const color = d3.scaleOrdinal(d3.schemeCategory10);
  .attr('height', 15)
  .attr('width', 15);

legend.append('text')
  .attr('x', 18)
  .attr('y', 10)
  .attr('dy', '.15em')
  .text((d, i) => d)
  .style('text-anchor', 'start')
  .style('font-size', 12);

// Now space the groups out after they have been appended:
const padding = 10;
legend.attr('transform', function (d, i) {
  return 'translate(' + (d3.sum(legendData, function (e, j) {
    if (j < i) { return legend.nodes()[j].getBBox().width; } else { return 0; }
  }) + padding * i) + ',0)';
});