Линейный график D3 — линия не отображается в правильных координатах

#d3.js

#d3.js

Вопрос:

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

Например, первая точка равна (4,2), но она начинается с (0,2) и так далее. Возможно, я где-то ошибаюсь. Пожалуйста, смотрите ниже привязку:

введите описание изображения здесь

Вот ссылка на stackblitz.

Вот код:

 maxAllowed = 60;
  graphData = [
    {
      hrCount: 4,
      resCount: 2
    },
    {
      hrCount: 8,
      resCount: 5
    },
    {
      hrCount: 12,
      resCount: 10
    },
    ...
const margin = { top: 25, right: 25, bottom: 25, left: 25 };
    const width =
      document.getElementById("svgcontainer").parentElement.offsetWidth -
      (margin.left   margin.right);
    const height =
      document.getElementById("svgcontainer").parentElement.offsetHeight -
      (margin.top   margin.bottom);

    // Remove any existing SVG
    d3.select("#svgcontainer")
      .selectAll("svg > *")
      .remove();

    // Group
    const g = d3
      .select("#svgcontainer")
      .append("svg")
      .attr("width", width   margin.left   margin.right)
      .attr("height", height   margin.top   margin.bottom)
      .append("g")
      .attr("transform", "translate("   margin.left   ", "   margin.top   ")");

    // Scale
    // x-scale
    const xScale = d3
      .scaleBand()
      .domain(this.graphData.map((d: any) => d.hrCount))
      .range([0, width]);
    // y-scale
    const yScale = d3
      .scaleLinear()
      .domain([0, this.maxAllowed])
      .range([height, 0]);

    // y-axis gridline
    g.append("g")
      .attr("class", "y-axis-grid")
      .call(
        d3
          .axisLeft(yScale)
          .tickSize(-width)
          .tickFormat("")
          .ticks(5)
      );

    // Axis
    // x-axis
    const xAxis = d3.axisBottom(xScale).tickSizeOuter(0);
    g.append("g")
      .attr("transform", "translate(0, "   height   ")")
      .attr("class", "graph-axis")
      .call(xAxis.scale(xScale))
      .append("text")
      .attr("x", width)
      .attr("y", -6)
      .attr("text-anchor", "end")
      .attr("font", "10px sans-serif")
      .attr("letter-spacing", "1px")
      .attr("fill", "#8997b1")
      .text("Hours");
    // y-axis
    const yAxis = d3
      .axisLeft(yScale)
      .ticks(5)
      .tickSizeOuter(0);
    g.append("g")
      .attr("class", "graph-axis")
      .call(yAxis.scale(yScale))
      .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .attr("font", "10px sans-serif")
      .attr("letter-spacing", "1px")
      .attr("fill", "#8997b1")
      .text("Resources");

    // Data line
    const line = d3
      .line()
      .x((d: any) => xScale(d.hrCount))
      .y((d: any) => yScale(d.resCount));
    const path = g
      .append("path")
      .attr("fill", "none")
      .attr("stroke", "#088dda")
      .attr("stroke-width", "2px")
      .attr("d", line(this.graphData));
    // Transition
    const totalLength = path.node().getTotalLength();
    path
      .attr("stroke-dasharray", totalLength   " "   totalLength)
      .attr("stroke-dashoffset", totalLength);
    path
      .transition()
      .duration(4000)
      .attr("stroke-dashoffset", 0);

    // Data dots
    g.selectAll("line-circle")
      .data(this.graphData)
      .enter()
      .append("circle")
      .attr("r", 4)
      .attr("fill", "#088dda")
      .attr("cx", (d: any) => xScale(d.hrCount))
      .attr("cy", (d: any) => yScale(d.resCount));
  }
 

Спасибо за помощь.

Комментарии:

1. Не используйте диапазонные шкалы для количественных переменных, вместо этого используйте линейную шкалу: stackblitz.com/edit/angular-ivy-kzph2f?file=src/app /…

2. @GerardoFurtado Спасибо, но мне также нужно показать те же значения по оси x, что и в данных. При этом масштаб делится на значения, кратные 5. Я попробовал ‘ticks (15)’, но это не разделяет значения, как ожидалось. Пожалуйста, помогите. Спасибо.

3. Если вам абсолютно необходимо использовать scaleBand (чего не следует, как указал @Gerardo Furtado), один из способов центрирования точек — использовать .x((d: any) => xScale(d.hrCount) xScale.bandwidth() / 2) .

4. @RubenHelsloot Это работает. Но также я постараюсь реализовать его с линейным масштабом. Спасибо