javascript - d3.js水平条形图问题

标签 javascript jquery reactjs d3.js charts

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

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

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

Bar chart Screenshot

要进行调试,请引用以下代码:

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>

最佳答案

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

如果您确实不想要它,您可以将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;
}

关于javascript - d3.js水平条形图问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61224958/

相关文章:

reactjs - Semantic-UI-React Loading 组件后面的这些单选按钮的 z 索引是否不正确?

javascript - HTML5 音频可视化工具?

javascript - 2 个完整页面之间的 JS 或 Css 页面滑动过渡

javascript - 如何使用 javascript 渲染 html

javascript - jQueryUI 模态添加功能到默认值

javascript - JQuery .animate() 菜单滑回

javascript - Bundle.js ReactJS 文件美化

javascript - $_POST 未读取 Axios 发布参数

javascript - 将包含对象的 3D 数组展平为 2D,通过其参数删除重复的对象

javascript - 获取 X,Y 坐标并在单击图标时传递值 (JQuery)