使用d3 + react绘制路径(折线图)

时间:2020-03-29 20:08:23

标签: javascript reactjs d3.js

使用Redux实现的React组件中的

D3折线图。

设法绘制xAxis和yAxis,但线路径为: MNaN,36LNaN,28.000000000000007LNaN,36LNaN,20LNaN,20LNaN,30.666666666666664LNaN,28.000000000000007LNaN,24.000000000000004

数据来自getDerivedStateFromProps生命周期中的nextProps,但未传递给 lineGenerator

这是我的组件:

import * as d3 from 'd3';
import React, { Component } from 'react';

const width = 400;
const height = 200;
const margin = { top: 20, right: 5, bottom: 20, left: 35 };
const green = '#00ded0';

class CPULineChart extends Component {
  state = {
    cpu: null, // svg path command for all cpu points
    // d3 helpers
    xScale: d3.scaleTime().range([margin.left, width - margin.right]),
    yScale: d3.scaleLinear().range([height - margin.bottom, margin.top]),
    lineGenerator: d3.line()
  };

  xAxis = d3
    .axisBottom()
    .scale(this.state.xScale)
    .tickFormat(d3.timeFormat('%b'));
  yAxis = d3.axisBottom().scale(this.state.yScale);

  static getDerivedStateFromProps(nextProps, prevState) {
    if (!nextProps.data) return null; // data hasn't been loaded yet so do nothing
    const { data } = nextProps;
    const { yScale, xScale, lineGenerator } = prevState;

    // data has changed, so recalculate scale domains
    const timeDomain = d3.extent(data, d => d.date);
    const cpuMax = d3.max(data, d => d.high);
    xScale.domain(timeDomain);
    yScale.domain([0, cpuMax]);

    // Calculate line for CPU
    lineGenerator.x(d => xScale(d.date));
    lineGenerator.y(d => yScale(d.high));

    const cpu = lineGenerator(data);

    console.log(cpu);
    return cpu;
  }

  componentDidUpdate() {
    d3.select(this.refs.xAxis).call(this.xAxis);
    d3.select(this.refs.yAxis).call(this.yAxis);
  }

  render() {
    return (
      <svg width={width} height={height}>
        <path d={this.state.cpu} fill="none" stroke={green} strokeWidth="2" />
        <g ref="xAxis" transform={`translate(0, ${height - margin.bottom})`} />
        <g ref="yAxis" transform={`translate(${margin.left}, 0)`} />
      </svg>
    );
  }
}

export default CPULineChart;

从父组件传递数据:

<CPULineChart data={data} />

和数据

 {
    "date": "2015-10-1 1:00 PM GMT+1:00",
    "high": 0.135,
    "low": 20
  },
  {
    "date": "2015-10-1 2:00 PM GMT+1:00",
    "high": 0.09,
    "low": 20
  },
  {
    "date": "2015-10-1 3:00 PM GMT+1:00",
    "high": 0.1,
    "low": 20
  }

1 个答案:

答案 0 :(得分:1)

对于xScale: d3.scaleTime()...,x值必须是Date()对象。传递/获取的数据包含以字符串形式提供的date属性-需要转换。用于timeDomain的{​​{1}}也需要与日期相关。

可以通过更改以下两行来解决问题:

xScale

与lineGenerator中的相同:

const timeDomain = d3.extent(data, d => new Date(d.date));