Координаты НАН на D3.Яш В4 макетов


Попытка использовать D3.Яш раскладов на картах на вход JSON вида:

var data = {
  "name": "Top",
  "frequency": 0,
  "children": [
  {
    "name": "Per",
    "frequency": 1287
  },
  {
    "name": "Tu",
    "frequency": 133,
    "children": [
    {
      "name": "Mel",
      "frequency": 50
    }
    ]
  }
  ]
}

Я застрял на получении X и y позиций, и я думал, что это из-за моего отсутствия знаний использования .сумма или .значение () для захвата частотного поля. Я хотел проверить свое предположение, поэтому я попробовал компоновку дерева, просто чтобы увидеть пространственно организованные данные:

var svg = d3.select(".chart").append("svg")
  .attr("height", "100%")
  .attr("width", "100%");

var root = d3.hierarchy(data);

var treeLayout = d3.tree().size([+svg.attr("width"), +svg.attr("height")]);

treeLayout(root);

var nodes = root.descendants();

svg.selectAll("circle").data(nodes)
      .enter().append("circle")
        .attr("r", function(d, i) {
          return 4;
        })
        .attr("cx", function(d, i) {
          return d.x;
        })
        .attr("cy", function(d, i) {
          return d.y;
        });

И HTML:

<style type="text/css">
  div.chart {
    height: 5000px;
  }
</style>
<div class="chart">
</div>

Регистрируя корень в консоли, я увидел, что поля x и y по-прежнему NaN. Видите ли вы ошибка в моем коде?

2 2

2 ответа:

Вы устанавливаете ширину и высоту SVG в процентах:

var svg = d3.select("body").append("svg")
    .attr("height", "100%")
    .attr("width", "100%");

Итак, когда вы используете геттер, вы получаете строку 100%:

var svg = d3.select("body").append("svg")
  .attr("height", "100%")
  .attr("width", "100%");

console.log(svg.attr("width"))
<script src="https://d3js.org/d3.v4.min.js"></script>

Конечно, использование унарного плюса с такой строкой дает вам NaN:

console.log(+"100%")

И вы передаете эти NaN s d3.tree().size().

Есть несколько решений, самое простое-это просто передачачисел в размер макета. Однако, как вы используете "100%", мы можем предположить, что вы не знаете размер SVG.

Итак, мое решение здесь (опять же, не единственное возможное) - это использование d3.style для получения атрибута в пикселях, а не в процентах (но все же в виде строки)...

var svg = d3.select("body").append("svg")
  .attr("height", "100%")
  .attr("width", "100%");

console.log(d3.style(svg.node(), "width"))
<script src="https://d3js.org/d3.v4.min.js"></script>

... и затем, используя parseInt() (или любой другой метод), чтобы избавиться от этого px:

var svg = d3.select("body").append("svg")
  .attr("height", "100%")
  .attr("width", "100%");

console.log(parseInt(d3.style(svg.node(), "width")))
<script src="https://d3js.org/d3.v4.min.js"></script>
Наконец, если вы не хотите иметь дело со строками, просто используйте getBoundingClientRect(), который вернет a число:

var svg = d3.select("body").append("svg")
  .attr("height", "100%")
  .attr("width", "100%");

console.log(svg.node().getBoundingClientRect().width);
<script src="https://d3js.org/d3.v4.min.js"></script>

Короткий ответ: вы определяете размер svg относительно размера окна (100% ширины и высоты страницы). С вашим текущим кодом это приводит к тому, что целое число none передается в d3.tree.size(), вызывая NaN. как указывает Херардо, это может легко преобразовываться из процента в значение пикселя, однако использование фиксированных значений ширины и высоты не является ужасной идеей при попытке получить небольшие примеры, подобные этому.

Если вы измените ширину и высоту на фиксированные значения, то ваш код работает. Я бы предложил делать это до тех пор, пока вам не станет более комфортно с D3 и тем, что вы пытаетесь достичь с помощью этого кода выше.