1. 程式人生 > >【譯】用 React 和 D3 建立圖表

【譯】用 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 建立簡單圖表是多麼容易。

(完)