привязка вложенных переменных d3

1

Я новичок в D3 и пытаюсь решить непростую задачу (по крайней мере для меня!) Вот мой образец данных.

var data = [
    {"x":1000, "y": {"10":100, "10.2":200, "10.3":300, "10.4":600}},
    {"x":1001, "y": {"9.2":60, "9.6":400, "10.1":20, "10.8":320, "11":20, "8.8":722}},
    {"x":1002, "y": {"9.8":80, "9.9":600, "9.2":40}},
    {"x":1003, "y": {"10.1":60, "10.3":400, "10.8":360, "9.6":88}},
    {"x":1004, "y": {"9.8":20, "10.4":450}}
];

Как связать это с помощью d3 для создания прямоугольников с атрибутами x= значение x, y= ключей объекта y, width= значения объекта y и height= любая заданная константа?

По существу, это будет иметь переменное количество прямоугольников для каждого x на основе количества элементов в y объекте.

Теги:
d3.js

1 ответ

1
Лучший ответ

Это, действительно, немного сложно, главным образом потому, что ваше свойство y содержит только один объект, а не массив объектов.

Мое решение здесь использует d3.entries, который, согласно API:

Возвращает массив, содержащий ключи свойств и значения указанного объекта (ассоциативный массив). Каждая запись представляет собой объект с атрибутом key и value, например {key: "foo", значение: 42}. Порядок возвращаемого массива не определен. (акцент мой)

Важно иметь массив, поэтому мы можем привязать данные (так как метод data() принимает только три вещи: массив, функцию или ничего).

Итак, в этом решении я использую внешние объекты для добавления групп...

var groups = svg.selectAll(null)
  .data(data)
  .enter()
  .append("g");

... и объект y каждого внешнего объекта для добавления прямоугольников...

var rects = groups.selectAll(null)
  .data(function(d) {
    return d3.entries(d.y)
  })
  .enter()
  .append("rect");

... и используя d3.entries() для преобразования объекта в массив объектов, который может использоваться с data().

Вот демонстрация (я изменил ваши фактические значения, поэтому мы можем лучше видеть прямоугольники):

var data = [{
  "x": 100,
  "y": {
    "10": 100,
    "20": 200,
    "26": 300,
    "35": 400
  }
}, {
  "x": 20,
  "y": {
    "50": 60,
    "59.6": 400,
    "70.1": 20,
    "80.8": 320,
    "88": 20,
    "98.8": 722
  }
}, {
  "x": 30,
  "y": {
    "109.8": 80,
    "119.9": 600,
    "139.2": 40
  }
}, {
  "x": 10,
  "y": {
    "150.1": 60,
    "170.3": 400,
    "190.8": 360,
    "209.6": 88
  }
}, {
  "x": 50,
  "y": {
    "259.8": 20,
    "280.4": 450
  }
}];

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

var constant = 5;

var svg = d3.select("svg");

var groups = svg.selectAll(null)
  .data(data)
  .enter()
  .append("g")
  .style("fill", function(d, i) {
    return colours(i)
  })

var rects = groups.selectAll(null)
  .data(function(d) {
    return d3.entries(d.y)
  })
  .enter()
  .append("rect");

rects.attr("y", function(d) {
    return +d.key
  })
  .attr("width", function(d) {
    return d.value
  })
  .attr("height", constant)
  .attr("x", function(d) {
    return d3.select(this.parentNode).datum().x;
  })
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="600" height="300"></svg>

Обратите внимание на то, как я получаю значения y и width и, особенно, значение x (доступ к исходной системе координат).

  • 0
    Большое спасибо за ваш быстрый ответ! Хотя я пытаюсь понять решение, я просто хочу упомянуть, что значения y являются идеальным решением с точки зрения извлечения данных, а не обязательным. Если может быть более чистое решение с некоторой реорганизацией значений y, например, для возврата массива ключей и значений, я мог бы изменить изменение данных для возврата такого результата или изменить его в самом слое JS. Еще раз спасибо!
  • 0
    Я не следующий ваш комментарий ... Мой ответ возвращает массив ключей и значений.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню