D3 - Вложенная круговая диаграмма не отображает все клинья - PullRequest
0 голосов
/ 20 февраля 2020

У меня были проблемы с графиком ap ie, который я пытался сделать. Наконец-то у меня работает внешнее кольцо, но на внутреннем кольце отображаются только некоторые части (на наружном кольце 3, на внутреннем кольце 6, но 3).

Кто-нибудь знает, что может быть не так с этим кодом? ? Обе системы работают нормально сами по себе, но по какой-то причине они не работают, когда я их соединяю.

Клинки для 20, 10 и 5 - это те, которые не отображаются, и так происходит каждый раз.

Имя класса ("ar c" ) тоже не имеет значения.

function makeDonut(svg) {
  var boundingBox = d3.select(svg).node().getBoundingClientRect();
  var h = boundingBox.height;
  var w = boundingBox.width;

  /*****   donut chart  *****/

  var data = [25, 40, 55];
  // arbitrary data

  var outerRadius = w/3;
  var innerRadius = 3*(outerRadius/4);
  var arc = d3.arc()
    .innerRadius(innerRadius)
    .outerRadius(outerRadius);

  var pie = d3.pie();

  // order: gold, silver, bronze
  var color = d3.scaleOrdinal()
    .range(['#e5ce0c', '#e5e4e0', '#a4610a']);

  var arcs = d3.select(svg).selectAll("g.arc")
    .data(pie(data))
    .enter()
    .append("g")
    .attr("class", "arc")
    .attr("transform", "translate(" + (w/2) + "," + ((h-25)/2) + ")");

  arcs.append("path")
  .attr("fill", function(d, i) {
    return color(i);
  })
  .attr("d", arc)
  .attr("stroke", "white")
  .style("stroke-width", "0.5px")
  .on('mouseover', function(d) {
    d3.select(this).attr('opacity', .7);

  })
  .on('mouseleave', function(d) {
    d3.select(this).attr('opacity', 1);
  });

  arcs.append("text")
    .attr("transform", function(d) {
      return "translate(" + arc.centroid(d) + ")";
    })
    .attr("text-anchor", "middle")
    .text(function(d) {
      return d.value;
    });

    /************ piechart ************/

    var dataset = [ 5, 10, 20, 45, 6, 25 ];
    // arbitrary dataset

    var outerRadius2 = 0.75 * (w/3);
    var innerRadius2 = 0;

    var arc2 = d3.arc()
      .innerRadius(innerRadius2)
      .outerRadius(outerRadius2);

    var pie2 = d3.pie();

    var color2 = d3.scaleOrdinal(d3.schemeCategory10);


    var arcs2 = d3.select(svg).selectAll("g.arc")
      .data(pie2(dataset))
      .enter()
      .append("g")
      .attr("class", "arc")
      .attr("transform", "translate(" + (w/2) + "," + ((h-25)/2) + ")");

    //Draw arc paths
    arcs2.append("path")
      .attr("fill", function(d, i) {
        return color2(i);
      })
      .attr("d", arc2);

    arcs2.append("text")
      .attr("transform", function(d) {
        return "translate(" + arc2.centroid(d) + ")";
      })
      .attr("text-anchor", "middle")
      .text(function(d) {
        return d.value;
      });
}

1 Ответ

1 голос
/ 20 февраля 2020

Метод ввода D3 создает элементы в DOM, где это необходимо, чтобы для каждого элемента в массиве данных был соответствующий элемент в DOM.

Для вашей кольцевой диаграммы, которую вы рисуете первой, вы selectAll("g.arc") - нет элементов g с классом arc, у вас есть пустой выбор. Поэтому, когда вы используете метод ввода, D3 создает один элемент для каждого элемента в массиве данных. Все, что связано с .enter() без метода .merge(), влияет только на эти введенные элементы.

Для вашего графика p ie, который вы рисуете вторым, вы selectAll("g.arc") - однако теперь их три g элементов с классом arc. Поэтому, когда вы используете здесь метод ввода, выбор ввода не включает элементы для первых трех элементов в массиве данных: они уже существуют . Вместо этого эти первые три элемента включены в выбор обновления.

Эта функция является основной для цикла ввода / обновления / выхода D3.

Если вы хотите ввести все, а не обновлять или не выходить из точек данных, тогда вы можете просто использовать .selectAll(null) который создаст пустой выбор, для которого выбор ввода создаст элемент для каждого элемента в массиве данных.

Если вы захотите изменить эти клинья / дуги позже, вы можете различить их, либо вводя их в разные элементы g (например: g1.selectAll("g.arc") и g2.selectAll("g.arc"). В качестве альтернативы, вы можете дать им разные имена классов в зависимости от того, p ie или пончик, как показано ниже:

var svg = d3.select("svg");
  var boundingBox = svg.node().getBoundingClientRect();
  var h = boundingBox.height;
  var w = boundingBox.width;

  /*****   donut chart  *****/

  var data = [25, 40, 55];
  // arbitrary data

  var outerRadius = w/3;
  var innerRadius = 3*(outerRadius/4);
  var arc = d3.arc()
    .innerRadius(innerRadius)
    .outerRadius(outerRadius);

  var pie = d3.pie();

  // order: gold, silver, bronze
  var color = d3.scaleOrdinal()
    .range(['#e5ce0c', '#e5e4e0', '#a4610a']);

  var arcs = svg.selectAll("donut")
    .data(pie(data))
    .enter()
    .append("g")
    .attr("class", "donut")
    .attr("transform", "translate(" + (w/2) + "," + ((h-25)/2) + ")");

  arcs.append("path")
  .attr("fill", function(d, i) {
    return color(i);
  })
  .attr("d", arc)
  .attr("stroke", "white")
  .style("stroke-width", "0.5px")
  .on('mouseover', function(d) {
    d3.select(this).attr('opacity', .7);

  })
  .on('mouseleave', function(d) {
    d3.select(this).attr('opacity', 1);
  });

  arcs.append("text")
    .attr("transform", function(d) {
      return "translate(" + arc.centroid(d) + ")";
    })
    .attr("text-anchor", "middle")
    .text(function(d) {
      return d.value;
    });

    /************ piechart ************/

    var dataset = [ 5, 10, 20, 45, 6, 25 ];
    // arbitrary dataset

    var outerRadius2 = 0.75 * (w/3);
    var innerRadius2 = 0;

    var arc2 = d3.arc()
      .innerRadius(innerRadius2)
      .outerRadius(outerRadius2);

    var pie2 = d3.pie();

    var color2 = d3.scaleOrdinal(d3.schemeCategory10);


    var arcs2 = svg.selectAll(".pie")
      .data(pie2(dataset))
      .enter()
      .append("g")
      .attr("class", "pie")
      .attr("transform", "translate(" + (w/2) + "," + ((h-25)/2) + ")");

    //Draw arc paths
    arcs2.append("path")
      .attr("fill", function(d, i) {
        return color2(i);
      })
      .attr("d", arc2);

    arcs2.append("text")
      .attr("transform", function(d) {
        return "translate(" + arc2.centroid(d) + ")";
      })
      .attr("text-anchor", "middle")
      .text(function(d) {
        return d.value;
      });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width=500 height=400></svg>
...