在React中使用D3.js實現數據可視化

數據可視化是指使用圖表、圖形等可視化對象以更清晰、更有效的方式進行數據通信的技術。

在web上,有許多庫可用來可視化數據,但最突出的是D3js庫。它已經成為數據可視化的事實,并贏得了許多開發人員的信任。

React是一個被許多開發人員使用的庫。在本文中,我們將了解如何使用React和D3創建既可重用又美觀的組件。

首先,讓我們簡要分析一下這些庫。

React

React是一個用于構建用戶界面的JavaScript庫。它使創建可重用組件變得容易,這些組件可以組合在一起形成更復雜的組件。

這些組件能夠自己維護它們的狀態。

D3

D3.js是一個基于數據操作文檔的JavaScript庫。它使用HTML、CSS和SVG使數據栩栩如生。

D3試圖提供一種基于數據的高效操作數據的方法,而不是提供框架來完成所有可能的功能。

D3是快速的,支持大數據集和動態行為的動畫和交互。

下面就來看看如何一起使用這兩個庫來創建動態數據可視化組件。

安裝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元素中的任何屬性,如classheight、widthfill。

接著我們向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)

條形圖放大了,但仍然是倒置的

接下來,我們將解決柱狀圖被倒置的問題,但在此之前,我們先來理解為什么圖表會被倒置。

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;

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被追加。

條形圖應該是這樣的:

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379