Как удалить пробелы между столбцами в сгруппированных гистограммах в d3 - PullRequest
1 голос
/ 26 мая 2020

Я столкнулся с проблемой удаления пробела между полосами.

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

Возможно ли это в d3?

Найдите изображение ниже

enter image description here

1 Ответ

0 голосов
/ 26 мая 2020

Я не вижу простого пути. Вы должны поиграть со смещениями по оси x.

вот мой пример. Надеюсь, это поможет ...

  const data = [
    {
      "model_name":"f1",
      "field1":19,
      "field2":83,
      "field3":100,
    },
    {
      "model_name":"f2",
      "field1":67,
    },
    {
      "model_name":"f3",
      "field1":10,
      "field3":100,
    },
    {
      "model_name":"f4",
      "field1":98,
      "field2":43,
      "field3":100,
    }
  ],
    all_keys = ["field1", "field2", "field3"]

  const container = d3.select('#bar_cont'),
    width = 500,
    height = 300,
    margin = {top: 30, right: 20, bottom: 30, left: 50},
    barPadding = .2

  const svg = container
    .append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr("transform", `translate(${margin.left},${margin.top})`);

  const xScale0 = d3.scaleBand().range([0, width - margin.left - margin.right]).padding(barPadding);
  const yScale = d3.scaleLinear().range([height - margin.top - margin.bottom, 0]);

  const xAxis = d3.axisBottom(xScale0)
  const yAxis = d3.axisLeft(yScale)

  xScale0.domain(data.map(d => d.model_name));
  yScale.domain([0, d3.max(data, d => d3.max(all_keys, k => d[k]))]);

  svg.selectAll(".groups")
    .data(data)
    .enter().append("g")
    .attr("class", "model_name")
    .each(function (group_data) {
      const bar_data = getBars(group_data),
        x_offset = groupOffset(group_data),
        group_keys = bar_data.map(d => d.name)
        xScale1 = d3.scaleBand()
          .domain(group_keys)
          .range([0, xScale0.bandwidth() - x_offset*2])
          .padding(barPadding);

      d3.select(this)
        .attr("transform", d => `translate(${xScale0(d.model_name) + x_offset},0)`)
        .selectAll(".bar")
        .data(bar_data)
        .enter()
        .append("rect")
        .attr("class", "bar")
        .style("fill","blue")
        .attr("x", d => xScale1(d.name))
        .attr("y", d => yScale(d.value))
        .attr("width", xScale1.bandwidth())
        .attr("height", d => {
          return height - margin.top - margin.bottom - yScale(d.value)
        });
    })

  // Add the X Axis
  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", `translate(0,${height - margin.top - margin.bottom})`)
    .call(xAxis);

  // Add the Y Axis
  svg.append("g")
    .attr("class", "y axis")
    .call(yAxis);

  function getBars(d) {
    const bars = [];
    all_keys.forEach(k => {
      if (d.hasOwnProperty(k)) bars.push({name:k, value: d[k], data: d})
    })
    return bars
  }

  function groupOffset(d) {
    const groupElementsCount = all_keys.reduce((acc, k) => (d.hasOwnProperty(k) ? acc+=1 : acc), 0),
      allElementsCount = all_keys.length,
      groupWidth = xScale0.bandwidth(),
      x_offset = (1 - (groupElementsCount / allElementsCount)) * groupWidth / 2

    return x_offset
  }
<div id="bar_cont"></div>
<script src="https://d3js.org/d3.v5.min.js"></script>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...