D3:在和弦图中附加名称

时间:2018-05-28 02:58:50

标签: d3.js

我是D3的新手,我正在尝试制作一个关于在欧洲歌唱大赛中投票的国家之间关系的和弦图。到目前为止,这是我的代码:

var names = ["Ukraine","Spain","Slovenia","Lithuania","Austria","Estonia","Norway","Portugal","UK","Serbia","Germany","Albania","France","Czech Republic","Denmark","Australia","Finland","Bulgaria","Moldova","Sweden","Hungary","Israel","Netherlands","Ireland","Cyprus","Italy","Armenia","Azerbaijan","Belarus","Belgium","Croatia","Macedonia","Georgia","Greece","Iceland","Latvia","Malta","Montenegro","Poland","Romania","Russia","San Marino","Switzerland"];

var opacityDefault = 0.7;

var matrix = [
  [0,14,12,5,0,4,0,8,0,0,0,0,0,3,0,0,0,0,12,0,15,0,0,4,8,0,0,0,2,4,1,0,0,7,0,0,8,0,7,12,0,0,4], //Ukraine
  [0,0,0,0,0,0,0,0,0,0,6,1,0,0,0,0,1,10,0,0,0,1,2,5,0,7,0,0,7,0,0,0,0,0,6,0,0,1,0,0,0,0,14], //Spain
  [5,0,4,6,1,4,0,0,0,0,0,0,0,1,0,7,0,1,7,0,0,0,0,2,0,0,0,8,0,0,0,0,0,6,0,0,0,0,4,0,0,0,3], //Slovenia
  [2,0,5,0,7,0,5,9,0,0,0,12,7,16,0,12,12,6,1,0,0,0,15,0,0,3,22,0,6,0,10,0,5,0,8,0,3,8,0,1,0,0,6],  //Lithuania
  [7,0,10,0,13,0,1,9,8,0,18,12,12,7,2,0,5,12,5,17,3,15,16,7,7,5,18,4,2,7,16,0,11,0,15,10,0,8,13,12,15,12,8], //Austria
  [4,3,0,5,4,12,0,16,3,2,7,6,0,18,4,0,7,3,5,7,13,0,0,7,10,8,0,3,5,2,2,7,0,5,2,12,9,10,8,0,12,5,19], //Estonia
  [0,7,18,0,4,0,4,0,3,0,8,5,10,2,0,5,0,0,0,4,7,0,0,0,12,1,6,9,5,7,0,3,7,7,0,0,5,0,0,0,0,5,0], //Norway
  [0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,8,0,0,3,0,0,0,0,0,0,0,0,0,0,13,0,0,7,0,0], //Portugal
  [0,0,0,1,0,0,1,0,0,0,3,0,0,2,3,2,10,0,0,0,0,0,0,3,6,6,0,0,0,0,0,0,0,2,1,0,0,0,8,0,0,0,0], //UK
  [0,10,0,3,0,0,0,0,0,8,0,0,0,0,3,12,0,0,0,0,0,0,0,1,1,0,0,0,0,0,7,2,0,24,0,0,0,12,0,0,0,0,0], //Serbia
  [0,5,0,14,24,3,4,7,13,16,24,3,6,3,14,3,16,8,3,14,8,7,18,8,13,12,6,10,3,5,6,2,1,0,0,1,4,18,8,11,7,4,8], //Germany
  [0,12,7,0,0,18,0,4,0,9,0,7,0,0,0,5,2,0,6,10,0,2,0,0,12,0,0,1,6,0,7,17,10,20,0,0,0,7,0,7,0,5,10], //Albania
  [19,0,0,0,0,0,8,4,10,0,2,0,5,10,12,6,4,0,0,9,0,11,8,0,0,0,0,0,4,9,5,5,0,0,0,9,2,0,6,3,15,2,5], //France
  [14,6,11,10,6,9,8,0,14,15,6,5,3,4,1,9,7,3,0,11,6,8,4,4,0,4,5,5,13,14,11,7,8,0,8,5,2,0,12,4,8,11,0], //Czech Republic
  [11,0,10,6,8,0,2,3,0,5,0,2,12,5,0,2,2,2,7,12,0,5,10,2,12,10,8,4,0,0,0,0,24,6,3,13,7,2,0,6,10,7,2], //Denmark
  [2,0,2,2,0,0,9,0,0,0,12,1,8,6,0,0,0,2,0,0,7,0,6,10,0,0,0,0,0,2,0,0,7,0,7,0,5,0,7,4,0,0,0], //Australia
  [0,0,0,0,0,5,0,0,0,0,0,4,9,0,0,0,0,0,3,3,0,0,0,0,0,4,12,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0], //Finland
  [0,6,1,0,0,7,9,6,5,6,1,14,6,0,14,8,10,5,5,0,11,0,0,0,0,0,7,2,12,0,0,5,0,4,0,10,0,2,1,2,0,0,7], //Bulgaria
  [6,11,6,9,0,1,0,3,0,0,0,4,0,7,2,8,1,19,6,0,0,0,0,6,10,7,1,6,10,11,8,11,2,8,0,0,24,0,10,0,0,6,6], //Moldova
  [6,2,1,8,8,7,7,12,2,8,11,2,0,12,4,0,0,0,8,7,0,8,13,5,1,12,5,12,12,12,2,8,1,2,12,8,11,5,10,6,12,12,0], //Sweden
  [1,8,2,0,2,0,0,0,0,3,0,0,0,0,0,0,0,10,2,0,2,0,0,0,0,0,3,12,4,0,5,6,0,3,2,8,0,0,3,10,2,3,0], //Hungary
  [22,13,8,24,15,4,14,15,22,19,3,17,17,8,6,16,13,8,22,15,22,16,7,24,9,18,0,9,10,18,14,10,16,1,11,19,18,6,0,10,7,1,2], //Israel
  [8,0,0,0,0,0,0,5,0,1,5,0,1,5,0,0,3,8,0,0,0,22,9,6,0,0,1,7,0,3,0,0,8,0,5,2,0,0,0,8,3,7,0], //Netherlands
  [0,0,0,4,4,0,0,0,6,8,4,13,4,0,7,3,0,1,14,4,0,4,1,1,5,12,0,0,0,0,1,0,3,0,15,2,0,6,0,7,4,0,3], //Ireland
  [4,14,15,7,11,18,22,10,20,1,6,8,16,1,20,8,17,12,8,3,13,11,7,3,8,7,12,10,0,19,15,24,7,6,9,7,11,10,2,8,7,14,5], //Cyprus
  [5,5,4,12,7,6,22,5,10,10,0,0,0,6,24,10,0,6,2,0,8,6,0,10,0,0,7,14,15,3,6,9,6,12,12,10,7,8,5,5,7,10,14], //Italy
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], //Armenia
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], //Azerbaijan
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], //Belarus
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], //Belgium
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], //Croatia
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], //Macedonia
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], //Georgia
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], //Greece
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], //Iceland
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], //Latvia
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], //Malta
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], //Montenegro
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], //Poland
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], //Romania
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], //Russia
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], //San Marino
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], //Switzerland

];

var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height"),
    outerRadius = Math.min(width, height) * 0.4 - 100,
    innerRadius = outerRadius - 20;

var formatValue = d3.formatPrefix(",.0", 1e3);

var chord = d3.chord()
    .padAngle(0.05)
    .sortSubgroups(d3.descending);

var arc = d3.arc()
    .innerRadius(innerRadius)
    .outerRadius(outerRadius);

var ribbon = d3.ribbon()
    .radius(innerRadius);

var color = d3.scaleOrdinal()
    .domain(d3.range(4))
    .range(["#4B5320", "#50C878", "#98FB98", "#679267","#2E8B57","#043927", "#0B6623","#9DC183","#708238", "#C7EA46", "#3F704D","#00A86B","8F9779"]);

var g = svg.append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
    .datum(chord(matrix));

var group = g.append("g")
    .attr("class", "groups")
  .selectAll("g")
  .data(function(chords) { return chords.groups; })
  .enter().append("g");


group.append("path")
    .style("fill", function(d) { return color(d.index); })
    .style("stroke", function(d) { return d3.rgb(color(d.index)).darker(); })
    .attr("d", arc);

var outerArcs = svg.selectAll("g.group")

outerArcs.append("path")
  .style("fill", function(d) { return colors(d.index); })
  .attr("d", arc);

outerArcs.append("text")
  .each(function(d) { d.angle = (d.startAngle + d.endAngle) / 2; })
  .attr("dy", ".35em")
  .attr("class", "titles")
  .attr("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; })
  .attr("transform", function(d) {
    if (outerArcs = 0) {
      width = 5.0;
    }
    return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")"
    + "translate(" + (outerRadius + 100) + ")"
    + (d.angle > Math.PI ? "rotate(180)" : "");
  })
  .text(function(i) { return names[i]; });

var groupTick = group.selectAll(".group-tick")
 .data(function(d) { return groupTicks(d, 1e3); })
 .enter().append("g")
 .attr("class", "group-tick")
  .attr("transform", function(d) { return "rotate(" + (d.angle * 180 / Math.PI - 90) + ") translate(" + outerRadius + ",0)"; });
groupTick.append("line")
    .attr("x2", 6);

groupTick
  //.filter(function(d) { return d.names; })
  .append("text")
  .attr("x", 8)
  .attr("dy", ".35em")
  .attr("transform", function(d) { return d.angle > Math.PI ? "rotate(180) translate(-16)" : null; })
  .style("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; })
  .text(function(d, i) { 
    console.log(d.id)
    return names[d.id]; 
  });

g.append("g")
    .attr("class", "ribbons")
  .selectAll("path")
  .data(function(chords) { return chords; })
  .enter().append("path")
    .attr("d", ribbon)
    .style("fill", function(d) { return color(d.target.index); })
    .style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); });



// Returns an array of tick angles and values for a given group and step.
function groupTicks(d, i) {
  var k = (d.endAngle - d.startAngle) / d.value;
  return d3.range(0, d.value,0.2).map(function(v, i) {
    return {
      angle: v * k + d.startAngle,
      label: i*100 % 5 ? null : v,
      id: i
    };
  });
}

</script>

目前,这些国家都是相互叠加的,我希望每个国家都拥有自己的名字/标签。没有参加决赛但仍参加比赛的国家的名字也没有出现,也需要修复。

我非常绝望,所以非常感谢帮助,欢呼!

1 个答案:

答案 0 :(得分:1)

您似乎重复了标签 - 您可以在两个位置添加文字:

groupTick
  .append("text")
  ...

以上:

outerArcs.append("text")
...

第一种方法最简单的修复,所以我将使用groupTick方法删除所有内容。如果您记录outerArcs.size(),您会看到您的选择不包含任何元素 - 类group没有元素(而是您想要groups):

var outerArcs = svg.selectAll("g.group")

因此,由于选择中没有元素,因此不会添加任何文本。

这也意味着outerArcs.append("path")...没有做任何事情 - 但是上面有group.append("path")...重复,所以我们可以删除

我们可以将已存在的选择与这些元素一起使用,而不是进行outerArcs选择:group

此外,当您尝试在此处访问数据的索引时:

.text(function(i) { return names[i]; });

参数名称是无关紧要的,虽然约定是索引是i,参数的顺序是设置内容的顺序,第一个参数是数据,索引是第二个参数,所以我们可以使用:

.text(function(d,i) { return names[i]; });

这里&#39;工作example删除重复的代码,使用group选项附加文本,并更改​​命名功能(我还减少了添加到外半径的数量从100像素开始间隔为10。)

这就是它的样子:

enter image description here