【译】用 React 和 D3 创建图表

本文翻译自:
https://dzone.com/articles/charts-with-modern-react-and-d3

本文将介绍如何利用 D3JS 和 ReactJS 来创建基础图表。

ReactJS 是一个用于制作可重用 Web 组件的前端 JavaScript 库。它的思路是(通过 React Native)将 Web 应用程序(以及移动应用程序)分解为较小的、独立的、可重用的组件。它使开发和维护中型到大型 Web 应用程序变得容易得多。

D3JS 是一个基于数据的 JavaScript 图形库。它可以帮助将数据绑定到 HTML 元素(SVG)并使用该数据操作 HTML 元素。你可以单独(不使用 ReactJS 或任何其他 Web 框架)用它来创建几乎所有任何数据可视化工具和仪表板。但是,如果你将其与 ReactJS 结合使用,那么就可以创建一个基于 Web 的现代化数据仪表板。

在本文中,我将展示如何使用 D3JS 和 ReactJS 的功能创建基本图表。后续,我将继续展示如何完全自定义图表并添加更多信息和交互内容。现在一切从简。让我们一起进入数据报告和可视化的世界吧。

在可视化数据之前,我们需要将数据传递给应用程序。现实生活中的应用程序,最有可能的是通过对服务器的 API 调用来完成此操作,从而向应用程序提供数据(通常为 JSON 或 XML 格式)。

这里我所举例的应用程序,数据存储在本地计算机上。我将使用 Node JS http 服务器来为其提供服务,以模拟真实的 API 调用。Http 服务器是一个用于设置服务器以提供静态文件的快速方法。我要做的就是创建一个文件夹(命名为 covid-data),存储数据文件(命名为 covid-data.csv),然后运行以下命令:

npx http-server --cors

注意:--cors 允许我们从(React)应用程序向同一台计算机上的服务器(http-server)发出请求。如果删除此标志,根据 CORS 策略,所有请求都将被拒绝。

现在我们已经运行了服务器并可以提供数据了。所以可以开始使用 React 和 D3 创建前端应用程序。

创建 React 应用程序的最佳方法是使用 Create React App:

npx create-react-app react-d3

完成此命令需要等待若干分钟。它将创建一个名为 react-d3 的新目录,并在其中创建一个基本的 React 应用程序。完成后,更改目录并启动应用程序:

Cd react-d3
Npm start

到这里,新的 React app 已经准备就绪,可以在端口3000上使用了。你只需启动浏览器,并确保通过访问以下链接来使其运行:

http://localhost:3000

你会看到React欢迎页面。

现在,我们需要做的就是启动项目。

首先,让我们尝试更改React的欢迎页面。打开 src / App.js,删除所有内容并将其替换为:

import React, { useEffect } from 'react';
import './App.css';
import draw from './draw'
function App() {
  useEffect(() => {
    draw()
  })
  return (
    <div className="App">
      <h1>D3 Simple Bar Chart</h1>
      <div id="chart-container"></div>
    </div>
  );
}
export default App;

在 return 方法中,我们添加了一个id为“chart-component”的 div。我们将使用 D3 在此处添加图表。

我们还使用了一个名为“useEffect”的钩子,该钩子在类组件中基本上等效于“componentDidMount”和“componentDidUpdate”。在此钩子中,我们运行“draw”函数,这个函数会运行我们绘制图表所需的所有 d3 命令。当然,你也可以从 API 中获取数据,但是此处我们使用 D3 在 draw 函数中来完成数据处理。

到目前为止,React 已经搞定了我们创建图表所需要的基础设施。现在,让我们看看如何使用D3获取数据并绘制图表。

在 src 文件夹中创建一个文件,并将其命名为“ draw.js”,然后将以下代码放入其中:

import * as d3 from 'd3'
async function draw () {
  const width = 800
  const height = 500
  const marginTop = 30
  const marginRight = 30
  const marginBottom = 30
  const marginLeft = 50
  const numOfCountries = 10
  const title = "COVID-19 Death Count"
  const svg = d3.select('#chart-container')
    .append('svg')
    .attr('width', width)
    .attr('height', height)
    .style('background-color', '#D3D3D3')

  svg.append('text')
    .attr('x', (marginLeft + width + marginRight) / 2)
    .attr('y', marginTop / 2)
    .attr('dy', '0.33em')
    .text(title)
    .attr('text-anchor', 'end')
  const dawData = await d3.csv('http://127.0.0.1:8080/covid-data.csv')
  const data = dawData.filter(d => d.date === "2020-04-11" && d.location !== "World").sort((a, b) => b.new_deaths - a.new_deaths).filter((d, i) => i < numOfCountries).map(d => ({date: d.date, location: d.location, new_deaths: +d.new_deaths}))
  console.log(data)
  const xScale = d3.scaleBand()
    .domain(data.map(d => d.location))
    .range([marginLeft, width - marginRight])
    .padding(0.3)
  const xAxis = d3.axisBottom()
    .scale(xScale)

  svg.append('g')
    .attr('transform', 'translate(0,' + (height - marginBottom) + ')')
    .call(xAxis)

  const yScale = d3.scaleLinear()
    .domain([0, d3.max(data, d => d.new_deaths)])
    .range([height - marginBottom, marginTop])

  const yAxis = d3.axisLeft()
    .scale(yScale)

  svg.append('g')
    .attr('transform', 'translate(' + marginLeft + ', 0)')
    .call(yAxis)

  svg
    .selectAll('rect')
    .data(data)
    .enter()
    .append('rect')
    .attr('x', d => xScale(d.location))
    .attr('y', d => yScale(d.new_deaths))
    .attr('width', xScale.bandwidth())
    .attr('height', d => height - marginBottom - yScale(d.new_deaths))
    .attr('fill', 'yellow')
}
export default draw

我将逐行解释这些代码。

第1行导入所有的 d3 方法。

在第3行中,我们定义了一个 draw 函数。而且在后面的第67行,我们将导出此函数,以便可以在 App.js 文件中使用它。

在第5至12行中,我们定义了用于图表外观和功能的所有常量。

在14到18行中,我们选择id为“chart-component”(创建于“App.js”文件)的div,向其添加SVG元素,并设置其宽度,高度和背景颜色。

在第20至25行中,我们将标题添加到 SVG,并将其放置在合适的位置。

在第27-29行中,我们使用 d3.csv 方法通过 API 调用获取数据。然后,我们对其进行过滤,排序和重组,并将其记录到控制台,以便我们可以查看数据并确保其符合预期。稍后我们可能会在将其投入生产之前删除第29行(即使我们不这样做,在构建应用程序的生产版本时,React 也会自动删除所有 console.logs)。

在第31-34行中,我们使用d3的极为有用的 scale 方法(在本例中就是 scaleBand)来定义 X 比例尺,以便我们可以将数据点转换为图表上正确位置的实点。

随后,在第36-37行中,我们定义了一个轴,在第39-41行中,我们将该轴与 SVG 连接。在第43-52行,对 Y 轴执行完全相同的操作。

最后,在第54-63行中,我们选择 SVG(到目前为止是一个空集)上的所有 bar(矩形),将数据附加到 bar上,对于这些数据点,我们将一个新 bar 附加到 SVG。然后,我们调整每个 bar 的x,y,宽度,高度和填充颜色。

就是这样。这是用 D3 和 React 创建的非常简单的图表。当然它缺少许多功能,也不能交互,但是稍后我们可以添加上去。本文的目的是向大家展示使用 D3 和现代 React 创建简单图表是多么容易。

(完)

【译】用 React 和 D3 创建图表

上一篇:SVG基础图形和D3.js


下一篇:Python 中 JSON和dict的转换,json的使用