安装React

安装react最简单的方法是使用react团队的create-react-app模板。
在本地机器上全局安装,以便可以重用,在终端上运行以下命令:

npm install -g create-react-app

接下来我们使用create-react-app模板创建一个新的app

create-react-app react-d3

下面进入新工程的目录

cd react-d3

安装D3

您可以使用CDN或通过NPM安装将D3库添加到应用程序

在本例中,我们使用NPM来安装:

npm install d3

现在准备工作做完了,我们可以在React中使用D3进行数据可视化开发了。

要在默认浏览器上预览创建的应用程序,请运行以下代码:

npm start

使用D3创建一个条形图(chart)

使用你喜欢的编辑器(我用vscode)打开工程,并打开文件 src/App.js.

这是当前在浏览器中呈现的组件。我们需要删除render()方法的内容,替换成我们自己的内容。

src目录中创建一个BarChart.js的文件,用来创建我们的条形图。

在文件中加入以下代码:

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

class BarChart extends Component {

}

export default BarChart;

我们将使用ComponentDidMount生命周期方法在BarChart组件已被装载到DOM中时显示条形图。

在BarChart组件中添加以下内容:

class BarChart extends Component {
    
  componentDidMount() {
    this.drawChart();
  }
}

我们将在drawChart方法中完成D3的绘制工作。

通常,在不使用React的情况下使用D3时,您不必将D3代码放入方法中,但这在React中非常重要,可以确保只在组件被挂载到DOM上时才显示图表

接下来,我们创建drawChart方法:

drawChart() {
  
  const data = [12, 5, 6, 6, 9, 10];
    
  const svg = d3.select("body").append("svg").attr("width", 700).attr("height", 300);
}
这个方法做了些什么呢?

首先,我们定义了一个变量data,它包含了我们想要可视化的数据。

其次,我们使用D3的方法定义了一个svg。我们使用SVG是因为它是可伸缩的,也就是说,无论屏幕有多大,或者您放大多少来查看数据,它都不会显示为像素化。

d3.select()用来选择文档中的HTML元素。它选择与传递参数相匹配的第一个元素,并为其创建一个节点。

在本例中,我们传递了body元素,稍后将对其进行更改,以使组件更加可重用。

append()方法的作用是:将一个HTML节点附加到所选项上,并返回该节点的句柄。

attr方法用于向元素添加属性。这可以是您通常添加到HTML元素中的任何属性,如classheightwidthfill

接着我们向body元素添加了一个svg元素,高:700,宽:300。

在我们创建的SVG变量下面,添加以下代码:

svg.selectAll("rect").data(data).enter().append("rect")

select方法一样,selectAll()选择与传递给它的参数匹配的元素。而selectAll()选择的所有与参数匹配的元素,而不仅仅是第一个。

data()方法用于将数据附加到所选HTML元素。

大多数情况下,这些元素不会被找到,因为大多数可视化处理的是动态数据,而且几乎不可能估计要表示的数据量。

enter()方法将我们从瓶颈中解救出来,因为它与append方法一起使用来创建丢失的节点,并且仍然可视化数据。

到目前为止,我们已经为每个数据点创建了节点。剩下的就是让它可见了。

为了使其可见,我们需要为每个数据集创建一个栏,设置一个宽度并动态更新每个栏的高度。

attr方法允许我们使用回调函数来处理动态数据:

selection.attr("property", (d, i) => {}) 

其中d为数点值,i为数据在数组中的索引。

首先,我们需要将每个数据点设置在条形图的x轴和y轴上的特定点上

首先,我们需要将每个数据点设置在条形图的x轴和y轴上的特定点上。我们使用“x”和“y”属性来实现这一点,其中“x”表示棒沿x轴(水平方向)的位置,“y”表示棒沿y轴的位置。

另外,我们需要设置每个数据点的宽度和高度。每个数据点的宽度是恒定的,因为条形图的宽度是相同的。

另一方面,高度取决于每个数据点的值。我们必须使用回调函数使条形图显示每个数据点的值。

我们将SVG变量修改为:

svg.selectAll("rect")
  .data(data)
  .enter()
  .append("rect")
  .attr("x", (d, i) => i * 70)
  .attr("y", 0)
  .attr("width", 25)
  .attr("height", (d, i) => d)
  .attr("fill", "green");

对于“x”,数组中数据点的每个索引都乘以一个常数整数70,使每个条的位置移动70。

y有一个常数y,我们很快就会改变。

宽度也有一个常数值65,小于图表中每个元素的位置,从而在每个元素之间创建一个空间。

条的高度取决于数据集中每个条目的值。

使用它,我们创建了一个条形图。然而,我们有两个问题:

  1. 图表中的条形图很小
  2. 图表也是倒过来的

为了解决上述问题,我们将每个数据乘以一个常量,比如10,以在不影响数据的情况下增加每个bar的大小:

.attr("height", (d, i) => d * 10)

React中使用D3.js实现数据可视化-小白菜博客
条形图放大了,但仍然是倒置的

接下来,我们将解决柱状图被倒置的问题,但在此之前,我们先来理解为什么图表会被倒置。

SVG的位置从上到下开始,因此使用y属性0将每个条放到SVG元素的顶部边缘。

为了解决这个问题,我们用SVG元素的高度减去每个条的高度:

.attr("y", (d, i) => h - 10 * d)

其中(10 * d)是我们之前计算得到的高度。

综合起来,BarChart组件将是:

class BarChart extends Component {
  componentDidMount() {
    this.drawChart();
  }
    
  drawChart() {
    const data = [12, 5, 6, 6, 9, 10];
    
    const svg = d3.select("body")
    .append("svg")
    .attr("width", w)
    .attr("height", h)
    .style("margin-left", 100);
                  
    svg.selectAll("rect")
      .data(data)
      .enter()
      .append("rect")
      .attr("x", (d, i) => i * 70)
      .attr("y", (d, i) => h - 10 * d)
      .attr("width", 65)
      .attr("height", (d, i) => d * 10)
      .attr("fill", "green")
  }
  render(){
    return <div id={"#" + this.props.id}></div>
  }
}
export default BarChart;
React中使用D3.js实现数据可视化-小白菜博客
Bar Chart in it’s glory

现在我们有了一个基本的条形图。我们再多做一点,添加标签。

向条形图添加标签

为了添加标签,我们在drawChart函数中添加了以下代码:

svg.selectAll("text")
  .data(data)
  .enter()
  .append("text")
  .text((d) => d)
  .attr("x", (d, i) => i * 70)
  .attr("y", (d, i) => h - (10 * d) - 3)

这与我们对这些条所做的类似,但是这次,text被追加。

条形图应该是这样的:

React中使用D3.js实现数据可视化-小白菜博客
Bar Chart with Labels

构建可重用的柱状图

React的一个重要部分是使组件可重用。

为此,我们需要删除提供的数据,然后通过props将其传递给组件。

SVG的宽度和高度也将通过props传递:

const data = [12, 5, 6, 6, 9, 10];

变成:

const data = this.props.data;

宽度和高度属性由:

const svg = d3.select("body").append("svg").attr("width", 700).attr("height", 300);

变成:

const svg = d3.select("body").append("svg")
  .attr("width", this.props.width)
  .attr("height", this.props.height);

在App.js文件中,我们现在可以使用组件并从父组件传递我们想要的数据:

class App extends Component {
  
  state = {
    data: [12, 5, 6, 6, 9, 10],
    width: 700,
    height: 500,
    id: root
  }

  render() {
    return (
      <div className="App">
        <BarChart data={this.state.data} width={this.state.width} height={this.state.height} />
      </div>
    );
  }
}

这样,我们可以在我们的React应用程序中任意地方重用条形图。

翻译自:https://blog.logrocket.com/data-visualization-in-react-using-react-d3-c35835af16d0