【问题标题】:d3.js horizontal Bar chart issued3.js 水平条形图问题
【发布时间】:2020-04-15 09:01:38
【问题描述】:

我是 d3 库的新手,正在使用 d3 库尝试一些图表。我可以使用 d3.js 库制作水平条形图,但我遇到了一些问题。

目前我遇到了麻烦,因为 x 轴上的最后一个值被裁剪了。我不想在图表中添加右边距。我想在 x 轴上显示带有刻度的最后一个标签。

我在下面的屏幕截图中突出显示了裁剪后的值:

调试请参考以下代码:

const margin = {
    top: 30,
    right: 0,
    bottom: 10,
    left: 100
};
const width= 1180;
const data = [{
        name: 'A',
        value: 2
    },
    {
        name: 'B',
        value: 20
    },
    {
        name: 'C',
        value: 15
    },
    {
        name: 'D',
        value: 8
    },
    {
        name: 'E',
        value: 1
    }
];
const barHeight = 20;
const yMax = d3.max(data, d => d.value);

const height =
    Math.ceil((data.length + 0.1) * barHeight) + margin.top + margin.bottom;
const x = d3
    .scaleLinear()
    .domain([0, yMax < 10 ? 10 : yMax])
    .range([margin.left, width - margin.right])
    .nice();
const y = d3
    .scaleBand()
    .domain(d3.range(data.length))
    .range([margin.top, height - margin.bottom])
    .padding(0.1);

const format = x.tickFormat(10, data.format);
const svg = d3.select('body').append('svg').attr('viewBox', [0, 0, width, height]);
const xAxis = g =>
    g
    .attr('class', 'chartxAxisText')
    .attr('transform', `translate(0,${margin.top})`)
    .call(d3.axisTop(x))

    .call(g => g.select('.domain').remove());
const yAxis = g =>
    g
    .attr('class', 'chartyAxisText')
    .attr('transform', `translate(${margin.left},0)`)
    .call(
        d3
        .axisLeft(y)
        .tickFormat(i => data[i].name)
        .tickSizeOuter(0)
    );

svg
    .append('g')
    .selectAll('rect')
    .data(data)
    .enter().append('rect')
    .attr('x', x(0))
    .attr('y', (d, i) => y(i))
    .attr('width', d => x(d.value) - x(0))
    .attr('height', y.bandwidth())
    .attr('class', 'chartbar')

svg
    .append('g')
    .attr('class', 'chartbarTextWrap')
    .selectAll('text')
    .data(data)
    .enter().append('text')
    .attr('x', d => x(d.value) - 4)
    .attr('y', (d, i) => y(i) + y.bandwidth() / 2)
    .attr('dy', '0.35em')
    .text(d => format(d.value))
    .attr('class', 'chartbarText');

svg.append('g').call(xAxis);

svg.append('g').call(yAxis);
.chartbarTextWrap {
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 1px;
    fill: #fff;
    text-anchor: end;
    pointer-events: none;
}
.chartbar {
    fill: red;
}
.chartxAxisText, .chartyAxisText {
    font-family: "Roboto", sans-serif;
    font-size: 16px;
    font-weight: 400;
    letter-spacing: 1px;
    color: #424242;
}
.chartxAxisText, .chartyAxisText {
   
    font-size: 16px;
    font-weight: 400;
    color: #424242;
}
svg {
  width:1180px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

<html>
<body></body>
</html>

【问题讨论】:

  • 为什么不const yMax = d3.max(data, d =&gt; d.value + 1);
  • 欢迎来到 stackOverflow。关于这个问题的一个评论:这将有助于了解所需的行为,因为可以有很多方法来解决这个问题。 Guidelines.

标签: javascript jquery reactjs d3.js charts


【解决方案1】:

在图表右侧添加一个小边距确实是最直接的解决方案。

如果实在不想要,可以将x轴文字标签向右对齐:

.chartxAxisText {
    text-anchor: end;
}

这在下面的片段中得到了证明。

const margin = {
    top: 30,
    right: 0,
    bottom: 10,
    left: 100
};
const width= 1180;
const data = [{
        name: 'A',
        value: 2
    },
    {
        name: 'B',
        value: 20
    },
    {
        name: 'C',
        value: 15
    },
    {
        name: 'D',
        value: 8
    },
    {
        name: 'E',
        value: 1
    }
];
const barHeight = 20;
const yMax = d3.max(data, d => d.value);

const height =
    Math.ceil((data.length + 0.1) * barHeight) + margin.top + margin.bottom;
const x = d3
    .scaleLinear()
    .domain([0, yMax < 10 ? 10 : yMax])
    .range([margin.left, width - margin.right]);
const y = d3
    .scaleBand()
    .domain(d3.range(data.length))
    .range([margin.top, height - margin.bottom])
    .padding(0.1);

const format = x.tickFormat(10, data.format);
const svg = d3.select('body').append('svg').attr('viewBox', [0, 0, width, height]);
const xAxis = g =>
    g
    .attr('class', 'chartxAxisText')
    .attr('transform', `translate(0,${margin.top})`)
    .call(d3.axisTop(x))

    .call(g => g.select('.domain').remove());
const yAxis = g =>
    g
    .attr('class', 'chartyAxisText')
    .attr('transform', `translate(${margin.left},0)`)
    .call(
        d3
        .axisLeft(y)
        .tickFormat(i => data[i].name)
        .tickSizeOuter(0)
    );

svg
    .append('g')
    .selectAll('rect')
    .data(data)
    .enter().append('rect')
    .attr('x', x(0))
    .attr('y', (d, i) => y(i))
    .attr('width', d => x(d.value) - x(0))
    .attr('height', y.bandwidth())
    .attr('class', 'chartbar')

svg
    .append('g')
    .attr('class', 'chartbarTextWrap')
    .selectAll('text')
    .data(data)
    .enter().append('text')
    .attr('x', d => x(d.value) - 4)
    .attr('y', (d, i) => y(i) + y.bandwidth() / 2)
    .attr('dy', '0.35em')
    .text(d => format(d.value))
    .attr('class', 'chartbarText');

svg.append('g').call(xAxis);

svg.append('g').call(yAxis);
.chartbarTextWrap {
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 1px;
    fill: #fff;
    text-anchor: end;
    pointer-events: none;
}
.chartbar {
    fill: red;
}
.chartxAxisText, .chartyAxisText {
    font-family: "Roboto", sans-serif;
    font-size: 16px;
    font-weight: 400;
    letter-spacing: 1px;
    color: #424242;
}
.chartxAxisText {
    text-anchor: end;
}
svg {
  width:1180px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

<html>
<body></body>
</html>

另一种选择是将所有标签保持原样,仅将最后一个标签向左对齐。这也可以在 CSS 中完成,规则如下:

.chartxAxisText text:last-child {
    text-anchor: end;
}

【讨论】:

  • 感谢您的解决方案,但如果我使用了 .chartxAxisText text { text-anchor: end; },那么刻度将不会与 x 轴标签对齐。如果我使用.chartxAxisText text:last-child { text-anchor: end; },那么最后一个刻度仍然是隐藏的。
  • 那么您希望图表的外观如何?请编辑问题以使其明确。
  • 由于使用.chartxAxisText text:last-child { text-anchor: end; } 最后一个数字,即显示 20,我只想为最后一个标签显示刻度。
  • 那么小余量就是解决方案?‍♂️
  • 感谢您的宝贵时间。如果除了margin right他们没有其他解决方案,那么我将只使用margin right。
猜你喜欢
  • 2021-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-08
  • 2017-02-19
  • 2019-08-24
  • 2014-01-03
相关资源
最近更新 更多