如何使 x 轴标签在 d3 中与 react 一起工作?

How to make x axis labels work in d3 with react?

这是我的代码示例:

import React, {Component} from 'react';
import {scaleOrdinal, axisBottom, select} from 'd3';

export default class BarChart extends Component {

  constructor(props) {
    super(props)
    this.renderSvg = this.renderSvg.bind(this);
  }

  componentDidMount() {
    this.renderSvg();
  }

  renderSvg() {
    const margin = 20;
    const width = 400;
    const height = 800;
    const data = ["why", "aren't", "you", "working"]
      .map((title) => ({title}));

    // create scalar for x axis
    const x = scaleOrdinal()
      .domain(data.map(({title}) => title))
      .range([0, width]);

    const xAxis = axisBottom(x);

    // create svg and append graph
    const svg = select("svg")
      .attr("width", width)
      .attr("height", height + margin)
      .append("g")

    svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);
  }

  render() {
    const {width, height, className} = this.props;
    return <div className="body">
      <svg className="svg" />
    </div>
  }
}

我已按照此站点上的示例进行操作:据我所知,https://bl.ocks.org/mbostock/3259783 非常接近,但我无法让它在预期的位置显示标签 regular/even 间隔。任何帮助将不胜感激,我是使用 d3 的新手。

问题是从 d3v3 到 d3v4/5 的转换。

d3.scale.ordinal() (v3) 用于多种音阶类型,由您进行的 rangeX() 调用决定。

在 d3v5 中 d3.scaleOrdinal() 表示序数比例并将序数域映射到序数范围。 https://github.com/d3/d3-scale/#scaleOrdinal 您只将范围设置为 2 值数组。因此每个域值在 2 个范围值上交替。

这是一个 d3v5 示例。 运行 时,我调整了高度以看到一些东西。使用开发人员工具查看轴刻度的交替转换。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
</head>
<body>
<div class="body">
<svg class="svg"/>
</div>
<script>
function renderSvg() {
  const margin = 20;
  const width = 400;
  const height = 100;
  const data = ["why", "aren't", "you", "working"]
    .map((title) => ({title}));

  // create scalar for x axis
  const x = d3.scaleOrdinal()
    .domain(data.map(({title}) => title))
    .range([0, width]);

  const xAxis = d3.axisBottom(x);

  // create svg and append graph
  const svg = d3.select("svg")
    .attr("width", width)
    .attr("height", height + margin)
    .append("g");

  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);
}

renderSvg();

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

示例代码使用 .rangePoints([0, width]) 并将 d3v5 转换为 d3.scalePoint()。现在序数域被映射到一个连续的范围。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
</head>
<body>
<div class="body">
<svg class="svg"/>
</div>
<script>
function renderSvg() {
  const margin = 20;
  const width = 400;
  const height = 100;
  const data = ["why", "aren't", "you", "working"]
    .map((title) => ({title}));

  // create scalar for x axis
  const x = d3.scalePoint()
    .domain(data.map(({title}) => title))
    .range([0, width]);

  const xAxis = d3.axisBottom(x);

  // create svg and append graph
  const svg = d3.select("svg")
    .attr("width", width)
    .attr("height", height + margin)
    .append("g");

  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);
}

renderSvg();

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