#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 Это работает. Но также я постараюсь реализовать его с линейным масштабом. Спасибо