D3 Добавить произвольное пространство между указанными c точками оси - PullRequest
0 голосов
/ 03 марта 2020

У меня есть гистограмма с накоплением, и мне нужно добавить интервалы и нарисовать линии на оси X после определенных c точек.

Пока это то, что я достиг, что почти точно что мне нужно (это скриншот бегущего графика):

enter image description here

Единственный способ, которым я смог найти создание линий и промежутков между ними Bars должен был создавать новые категории (называемые ими внутренне «separatorX») со значением 0, а затем скрывать его метку, когда он содержит слово «разделитель», но это выглядит очень странно.

Моя конечная цель состоит в том, чтобы найти более элегантный способ добавить дополнительное поле или интервал для указанных c точек оси X, поэтому не нужно создавать новые и ненужные пустые категории. Кроме того, я хотел бы настроить значение поля / интервала для каждой точки, чтобы не все они занимали одно и то же пространство.

Это фрагмент структуры данных, которая у меня есть прямо сейчас:

const data = [
{"phase":"0","total":1887,"subphase1":100,"subphase2":523,"subphase3":397,"subphase4":593,"subphase5":274},
{"phase":"1","total":2367,"subphase1":100,"subphase2":402,"subphase3":649,"subphase4":723,"subphase5":493},
{"phase":"2","total":1883,"subphase1":100,"subphase2":623,"subphase3":278,"subphase4":552,"subphase5":330},
{"phase":"3","total":1744,"subphase1":100,"subphase2":174,"subphase3":827,"subphase4":379,"subphase5":264},
{"phase":"separator1","total":0,"subphase1":0,"subphase2":0,"subphase3":0,"subphase4":0,"subphase5":0},
{"phase":"5","total":2414,"subphase1":100,"subphase2":727,"subphase3":406,"subphase4":362,"subphase5":819},
{"phase":"6","total":2124,"subphase1":100,"subphase2":607,"subphase3":434,"subphase4":619,"subphase5":364},
{"phase":"separator2","total":0,"subphase1":0,"subphase2":0,"subphase3":0,"subphase4":0,"subphase5":0},
{"phase":"separator3","total":0,"subphase1":0,"subphase2":0,"subphase3":0,"subphase4":0,"subphase5":0},
{"phase":"9","total":1643,"subphase1":100,"subphase2":303,"subphase3":256,"subphase4":779,"subphase5":205},
{"phase":"10","total":2213,"subphase1":100,"subphase2":643,"subphase3":778,"subphase4":486,"subphase5":206}
...
]

И это функция, в которой я определяю xScale (что, я думаю, именно там может произойти исправление):

const xScale = d3
 .scaleBand(
   data.map(d => d.phase),
   [margin.left, width - margin.right]
 )
 .padding(0.5);

Заранее спасибо всем, кто читает это! Любая помощь будет принята с благодарностью !!!

Вот вам пример:

const data = this.props.data;

const width = 700;
const height = 500;
const margin = {
    top: 10,
    right: 0,
    bottom: 60,
    left: 42
};

const barWidth = 12;
const containerBarWidth = barWidth + 16;

// Specific
const barColors = [Colors.TUNDORA, Colors.SILVER_CHALICE, Colors.SAN_MARINO, Colors.VIKING, Colors.SHAMROCK];
const colors = d3.scaleOrdinal(data.categories, barColors);

// Scales
const xScale = d3
    .scaleBand(
        data.map(d => d.phase),
        [margin.left, width - margin.right]
    )
    .padding(0.5);

const yScale = d3.scaleLinear(
    [0, d3.max(data, d => d.total + d.total * 0.1)],
    [height - margin.bottom, margin.top + 55]
);

// Axis
const xAxis = d3.axisBottom(xScale);
const yAxis = d3.axisLeft(yScale).ticks(4);

// Data preparation
const stack = d3.stack().keys(data.categories);
const chartData = stack(data);

// SVG
const svg = d3
    .select(this._rootNode)
    .append("svg")
    .attr("width", width)
    .attr("height", height);

// Bars
const groups = svg
    .append("g")
    .selectAll("g")
    .data(chartData)
    .join("g")
    .style("fill", (d, i) => colors(d.key));

groups
    .selectAll("rect")
    .data(d => d)
    .join("rect")
    .attr("x", d => xScale(d.data.phase))
    .attr("y", d => yScale(d[1]))
    .attr("height", d => yScale(d[0]) - yScale(d[1]))
    .attr("width", d => barWidth)
    .attr("stroke", "white")
    .attr("stroke-width", 2);

let separators = ["separator1", "separator3", "separator4", "separator6", "separator7"];
separators.forEach(separator => {
    const line = svg
        .append("g")
        .attr(
            "transform",
            "translate(" + (xScale(separator) - xScale.step() * xScale.padding() * 0.5 + 16) + ", 0)"
        );

    line.append("line")
        .attr("y1", margin.top)
        .attr("y2", height - margin.bottom)
        .style("stroke", Colors.ALTO)
        .style("shape-rendering", "crispEdges");
});

let groupTitlesAnchors = [
    { anchor: "0", title: "Group 1 >" },
    { anchor: "5", title: "Group 2 >" },
    { anchor: "9", title: "Group 3 >" },
    { anchor: "13", title: "Group 4 >" },
    { anchor: "17", title: "Group 5 >" },
    { anchor: "22", title: "Group 6 >" }
];

groupTitlesAnchors.forEach(group => {
    const point = svg
        .append("g")
        .style("font", "12px Arial")
        .attr("transform", "translate(" + (xScale(group.anchor) - xScale.step() + 10) + ", 36)");

    point
        .append("text")
        .text(group.title)
        .style("user-select", "none")
        .attr("x", 20);
});

// Axis
svg.append("g")
    .style("font", "12px Arial")
    .attr("transform", `translate(0,${height - margin.bottom})`)
    .attr("class", "xAxis")
    .call(
        xAxis.tickFormat((d, i) => {
            return d.includes("separator") ? `separator${i}` : i;
        })
    )
    .selectAll("text")
    .attr("y", 6)
    .attr("x", 6)
    .attr("transform", "rotate(45)")
    .style("text-anchor", "start");

svg.append("g")
    .style("font", "12px Arial")
    .attr("transform", `translate(${margin.left}, -1)`)
    .attr("class", "yAxis")
    .call(yAxis);

// Groups/Labels top separator
svg.append("line")
    .style("stroke", Colors.ALTO)
    .attr("x1", margin.left)
    .attr("y1", margin.top + 43)
    .attr("x2", width)
    .attr("y2", margin.top + 43)
    .style("shape-rendering", "crispEdges");

// Borders
svg.append("line")
    .style("stroke", Colors.ALTO)
    .attr("x1", margin.left)
    .attr("y1", margin.top + 1)
    .attr("x2", width)
    .attr("y2", margin.top + 1)
    .style("shape-rendering", "crispEdges");

svg.append("line")
    .style("stroke", Colors.ALTO)
    .attr("x1", width)
    .attr("y1", margin.top)
    .attr("x2", width)
    .attr("y2", height - margin.bottom)
    .style("shape-rendering", "crispEdges");

svg.append("line")
    .style("stroke", Colors.ALTO)
    .attr("x1", margin.left)
    .attr("y1", margin.top)
    .attr("x2", margin.left)
    .attr("y2", height - margin.bottom - 1)
    .style("shape-rendering", "crispEdges");

svg.append("line")
    .style("stroke", Colors.ALTO)
    .attr("x1", margin.left)
    .attr("y1", height - margin.bottom)
    .attr("x2", width)
    .attr("y2", height - margin.bottom)
    .style("shape-rendering", "crispEdges");
...