简体   繁体   English

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

[英]Draw a path (line chart) with d3 + react

D3 Line chart within a React Component with Redux implementation.带有 Redux 实现的 React 组件中的 D3 折线图。

Managed to draw xAxis and yAxis but line path is: MNaN,36LNaN,28.000000000000007LNaN,36LNaN,20LNaN,20LNaN,30.666666666666664LNaN,28.000000000000007LNaN,24.000000000000004设法绘制 xAxis 和 yAxis 但线路径是: MNaN,36LNaN,28.0000000000000007LNaN,36LNaN,20LNaN,20LNaN,30.6666666666666664LNaN,28.000000000000000004LNaN

Data comes from nextProps in getDerivedStateFromProps lifecycle but not being passed into the lineGenerator .数据来自 getDerivedStateFromProps 生命周期中的 nextProps 但没有传递到lineGenerator

This is my component:这是我的组件:

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;

Passing data from parent component:从父组件传递数据:

<CPULineChart data={data} />

And 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
  }

With xScale: d3.scaleTime()... x values needs to be a Date() objects.使用xScale: d3.scaleTime()... x 值需要是Date()对象。 Passed/fetched data contains date properties provided as strings - needs conversion.传递/获取的数据包含作为字符串提供的date属性 - 需要转换。 timeDomain used for xScale needs to be date related, too.用于xScale timeDomain需要与日期相关。

Problem can be solved by changing these two lines:可以通过更改以下两行来解决问题:

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

and same in lineGenerator:和 lineGenerator 相同:

lineGenerator.x(d => xScale(new Date(d.date)));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM