使用JavaScript和D3.js實現資料視覺化

TigerJin發表於2021-09-09

歡迎大家前往騰訊雲+社群,獲取更多騰訊海量技術實踐乾貨哦~

本文由獨木橋先生 發表於雲+社群專欄

介紹

D3.js是一個JavaScript庫。它的全稱是Data-Driven Documents(資料驅動文件),並且它被稱為一個互動和動態的資料視覺化庫網路。2011年2月首次釋出,在撰寫本文時,最新的穩定版本是4.4版本,並且不斷更新。D3利用可縮放向量圖形SVG格式,允許您渲染可放大或縮小的形狀,線條和填充,而不會降低質量。本教程將指導您使用JavaScript D3庫建立條形圖。

準備

為了充分利用本教程,您應該熟悉JavaScript程式語言以及CSS和HTML的知識。

儘管你將使用CSS來進行D3的樣式設定,但值得注意的是,很多在HTML上使用的標準的CSS在SVG的使用方式會不一樣-也就是說,你會用stroke,而不是border,使用fill而不是color

我們將使用文字編輯器和Web瀏覽器。出於測試目的,建議使用工具來檢查和除錯JavaScript、HTML和CSS,例如Firefox Developer ToolsChrome DevTools

第一步 - 建立檔案和參考D3

讓我們首先建立一個目錄來儲存我們所有的檔案。您可以隨意呼叫它,我們將其稱為D3專案。建立後,進入目錄。

mkdir D3-project
cd D3-project
複製程式碼

要使用D3的功能,您必須在網頁中包含d3.js檔案。它長約16,000行,大小約500kb。

讓我們用curl來將檔案下載到我們的目錄中。

要下載最適合包含專案的壓縮版本,請輸入:

curl https://d3js.org/d3.v4.min.js --output d3.min.js
複製程式碼

如果您打算閱讀D3程式碼,最好通過輸入以下內容來獲得未壓縮版本:

curl https://d3js.org/d3.v4.js --output d3.js
複製程式碼

我們將在本教程中使用d3.min.js檔案,請在HTML檔案中引用d3.js。

由於D3是模組化的,您可以通過僅拉入您將使用的模組來減小檔案大小。

下載D3後,讓我們設定CSS和HTML檔案。您可以選擇要在此檔案上使用的文字編輯器,例如nano。我們將從CSS檔案style.css開始,以便我們可以立即從HTML檔案連結到它。

nano style.css
複製程式碼

我們將從一個標準的CSS宣告開始,將頁面設定為100%高度且無邊距。

html, body {
  margin: 0;
  height: 100%;
}
複製程式碼

您現在可以儲存並關閉CSS檔案。

接下來我們將建立我們的JavaScript檔案,我們將其命名barchart.js,我們將為此示例製作條形圖。使用touch命令建立檔案,暫時不編輯。

touch barchart.js
複製程式碼

現在,讓我們將所有這些元素連線到一個HTML檔案,我們將其稱之為barchart.html:

nano barchart.html
複製程式碼

我們可以像大多數其他HTML檔案一樣設定此檔案,在其中我們將引用我們剛建立的style.css檔案、barchart.js檔案和指令碼d3.min.js。編輯barchart.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Bar Chart</title>
    <link rel="stylesheet" type="text/css" href="style.css">

    <!-- Alternatively use d3.js here -->
    <script type="text/javascript" src="d3.min.js"></script>

  </head>

  <body>
    <script type="text/javascript" src="barchart.js"></script>
  </body>
</html>
複製程式碼

儲存並關閉。

第二步 - 在JavaScript中設定SVG

我們現在可以使用我們選擇的文字編輯器開啟檔案barchart.js

nano barchart.js
複製程式碼

讓我們首先新增一個數字陣列,我們將其用作條形圖的基礎,編輯barchart.js

var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];
複製程式碼

接下來,我們需要建立SVG元素。這是我們儲存所有圖形的地方。在D3中,我們用d3.select來讓瀏覽器搜尋元素。

我們可以使用d3.select("body").append("svg");執行此操作。編輯barchart.js

var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];

var svg = d3.select("body").append("svg");
複製程式碼

如果我們現在載入barchart.html到我們的Web瀏覽器中,我們應該能夠使用我們的開發人員工具檢查DOM或文件物件模型,並將滑鼠懸停在SVG框上。

img

回到我們的JavaScript檔案中,我們可以將屬性連結到SVG,使其成為網頁的完整高度和寬度。我們將.attr()用於屬性。為了讓它更具可讀性。確保將分號向下移動到變數宣告的末尾。編輯barchart.js

var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];

var svg = d3.select("body").append("svg")
          .attr("height","100%")
          .attr("width","100%");
複製程式碼

如果您在瀏覽器中重新載入頁面,則應該會在滑鼠懸停DOM時看到一個佔據整個螢幕的矩形。

第三步 - 新增矩形

隨著我們的SVG準備就緒,我們可以開始將我們資料集的矩形新增到JavaScript檔案中,編輯barchart.js

var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];

var svg = d3.select("body").append("svg")
          .attr("height","100%")
          .attr("width","100%");

svg.selectAll("rect")
    .data(dataArray)
    .enter().append("rect");
複製程式碼

與上面的d3.select一樣,讓瀏覽器搜尋元素。這一次,它是一個矩形陣列。因為它是一個陣列,我們使用d3.selectAlld3.selectAll("rect"),因為它是一個矩形陣列。如果瀏覽器找到矩形,它將在選擇中返回它們,如果它是空的,它將返回空。使用D3,您必須首先選擇您要處理的元素。

我們配合這個矩形用.data(dataArray)陣列儲存在dataArray的資料。

要為選擇中的每個專案(對應於資料陣列)實際新增一個矩形,我們還將新增.enter().append("rect");以附加矩形。在此示例中,將有9個矩形對應於陣列中的9個數字。

如果您現在重新載入頁面,您將看不到任何矩形,但如果您檢查DOM,您將看到在那裡定義的9個矩形。

img

我們還沒有為矩形設定屬性以使它們可見,所以現在新增它們。

設定形狀的屬性

我們可以通過使用.attr(),與為SVG定義屬性相同的方式向形狀新增屬性。D3中的每個形狀將具有不同的屬性,具體取決於它們的定義和繪製方式。

我們的矩形將包含4個屬性:

  • ("height", "height_in_pixels") 對應矩形的高度
  • ("width", "width_in_pixels")對應矩形的寬度
  • ("x", "distance_in_pixels")代表與瀏覽器視窗左側的距離
  • ("y", "distance_in_pixels")代表與瀏覽器視窗頂部的距離

因此,如果我們想要長度為250畫素,寬40畫素,距離瀏覽器左側25畫素,距離頂部50畫素的矩形,我們將編寫如下程式碼:


var svg = d3.select("body").append("svg")
          .attr("height","100%")
          .attr("width","100%");

svg.selectAll("rect")
    .data(dataArray)
    .enter().append("rect")
          .attr("height","250")
          .attr("width","40")
          .attr("x","25")
          .attr("y","50");
複製程式碼

如果我們重新整理瀏覽器,我們會看到所有矩形重疊:

img

預設情況下,D3中的形狀填充為黑色,但我們可以稍後修改,因為我們需要首先解決矩形的定位和大小。

使矩形反映資料

目前,我們陣列中的所有矩形沿X軸具有相同的位置,並且不代表高度方面的資料。要修改矩形的位置和大小,我們需要為我們的一些屬性引入函式。新增函式將使值成為動態而非手動。讓我們從修改x屬性開始。目前,該行程式碼如下所示:

        .attr("x","25")
複製程式碼

我們將用一個函式替換25畫素的數字。我們將傳遞由D3定義的兩個變數function(),代表資料點和索引。索引告訴我們陣列中資料點的位置。d用於資料點和i索引的慣例,例如function(d,i),但您可以使用您想要的任何變數。

JavaScript將迭代di。讓我們為它迭代的每個索引新增間距,以便每個矩形間隔開。為此,我們可以將索引乘以i一定數量的畫素。我們現在將使用60,但您可以決定哪種間距適合您。我們新的X軸屬性行現在看起來像這樣:

        .attr("x", function(d, i) {return i * 60;})
複製程式碼

但是,如果我們現在執行程式碼,我們會看到矩形在瀏覽器的左側齊平,所以讓我們在那裡新增一些額外的間距,比如距邊緣25個畫素。現在我們的完整程式碼應如下所示:

var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];

var svg = d3.select("body").append("svg")
          .attr("height","100%")
          .attr("width","100%");

svg.selectAll("rect")
    .data(dataArray)
    .enter().append("rect")
          .attr("height","250")
          .attr("width","40")
          .attr("x", function(d, i) {return (i * 60) + 25})
          .attr("y","50");
複製程式碼

如果我們此時重新整理瀏覽器,我們會看到如下所示的內容:

img

現在我們有沿X軸間隔開的矩形,代表我們陣列中的每個專案。接下來,讓矩形的高度反映陣列中的資料。

我們現在將使用該height屬性,並將新增一個類似於我們新增到x屬性中的函式。讓我們通過傳遞變數開始difunction,並返回dd代表資料點。

.attr("height", function(d, i) {return (d)})

如果你現在執行程式碼,你會注意到兩件事。首先,矩形相當小,其次是它們附著在圖表的頂部而不是底部。

img

為了解決矩形的小尺寸,讓我們乘以d返回的:

          .attr("height", function(d, i) {return (d * 10)})
複製程式碼

現在矩形的大小更大,但它們仍然從上到下顯示。瀏覽器通常從左上角到右下角閱讀網頁,而我們從下到上閱讀條形圖。要重新定位矩形,我們將修改y屬性以減去頂部的空間。

再次,我們將使用function(d,i),並且我們將返回一個高於我們條形圖最高值的Y值,比方說400。我們將從400減去返回的高度(d * 10),以便我們的行現在看起來像這樣:

          .attr("y", function(d, i) {return 400 - (d * 10)});
複製程式碼

我們來看看我們的完整JavaScript程式碼:

var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];

var svg = d3.select("body").append("svg")
          .attr("height","100%")
          .attr("width","100%");

svg.selectAll("rect")
    .data(dataArray)
    .enter().append("rect")
          .attr("height", function(d, i) {return (d * 10)})
          .attr("width","40")
          .attr("x", function(d, i) {return (i * 60) + 25})
          .attr("y", function(d, i) {return 400 - (d * 10)});
複製程式碼

此時,當我們重新載入頁面時,我們會看到一個條形圖,我們可以從下到上閱讀:

img

現在,我們可以設計圖表的樣式。

第四步 - 使用D3設定樣式

我們將使用我們的CSS檔案來設計我們的D3形狀,但首先,為了使這項工作更容易,我們將在JavaScript檔案中為我們的矩形提供一個類名,我們可以在CSS檔案中引用它。

新增類就像使用點表示法新增任何其他屬性一樣。我們稱之為班級bar,因為它是一個條形圖,但只要所有引用都引用相同的名稱,我們就可以呼叫它。我們的語法如下所示:

          .attr("class", "bar")
複製程式碼

我們可以在任何地方新增此屬性。將它保留為第一個屬性可以使我們的CSS檔案更容易引用。

var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];

var svg = d3.select("body").append("svg")
          .attr("height","100%")
          .attr("width","100%");

svg.selectAll("rect")
    .data(dataArray)
    .enter().append("rect")
          .attr("class", "bar")
          .attr("height", function(d, i) {return (d * 10)})
          .attr("width","40")
          .attr("x", function(d, i) {return (i * 60) + 25})
          .attr("y", function(d, i) {return 400 - (d * 10)});
複製程式碼

現在,讓我們切換到我們的style.css檔案,目前看起來像這樣:

html, body {
  margin: 0;
  height: 100%
}
複製程式碼

我們可以通過更改填充顏色來開始修改矩形,引用我們剛剛建立的bar類別:

style.css
html, body {
  margin: 0;
  height: 100%
}

.bar {
  fill: blue
}
複製程式碼

在這裡,我們將矩形設為藍色,我們也可以為它們分配一個十六進位制顏色程式碼,如下所示:

.bar {
  fill: #0080FF
}
複製程式碼

此時,我們的矩形看起來像這樣:

img

我們可以為矩形提供其他值,例如用stroke以特定顏色勾勒出矩形,以及stroke-width

html, body {
  margin: 0;
  height: 100%
}

.bar {
  fill: #0080FF;
  stroke: black;
  stroke-width: 5
}
複製程式碼

這將為我們的矩形提供寬度為5畫素的黑色輪廓。

img

此外,我們可以通過在滑鼠懸停時新增條形顏色樣式來為我們的圖表新增一些互動性:

.bar:hover {
  fill: red
}
複製程式碼

現在,當我們將滑鼠懸停在其中一個矩形上時,該特定矩形將變為紅色:

img

或者,您可以通過新增其他屬性來設定JavaScript檔案中的形狀樣式。在矩形塊中,我們將像其他.attr()屬性一樣編寫這些。因此,在矩形周圍新增黑色筆劃將被寫為.attr("stroke", "black")。我們還要新增stroke-width個畫素,並確保將分號向下移動。

...
svg.selectAll("rect")
    .data(dataArray)
    .enter().append("rect")
          .attr("class", "bar")
          .attr("height", function(d, i) {return (d * 10)})
          .attr("width","40")
          .attr("x", function(d, i) {return (i * 60) + 25})
          .attr("y", function(d, i) {return 400 - (d * 10)})
          .attr("stroke", "black")
          .attr("stroke-width", "5");
複製程式碼

您可以選擇如何決定樣式和檔案樣式。在這個例子中,我們將在style.css檔案中操作,並將其限制為填充顏色和懸停填充:

html, body {
  margin: 0;
  height: 100%
}

.bar {
  fill: #0080FF
}

.bar:hover {
  fill: #003366
}
複製程式碼

在網路上處理顏色時,重要的是要牢記您的觀眾並努力包含儘可能普遍可訪問的顏色。

第五步 - 新增標籤

我們的最後一步是以標籤的形式在我們的圖表中新增一些可量化的標記。這些標籤將對應於我們陣列中的數字。

新增文字類似於新增上面我們所做的矩形形狀。我們需要選擇文字,然後將其附加到SVG。我們還將它與我們建立的dataArray聯絡起來。我們將使用"text",而不是"rect",但一般格式和我們在上面新增矩形所做的類似。我們將這些行新增到barchart.js檔案的底部。

var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];

var svg = d3.select("body").append("svg")
          .attr("height","100%")
          .attr("width","100%");

svg.selectAll("rect")
    .data(dataArray)
    .enter().append("rect")
          .attr("class", "bar")
          .attr("height", function(d, i) {return (d * 10)})
          .attr("width","40")
          .attr("x", function(d, i) {return (i * 60) + 25})
          .attr("y", function(d, i) {return 400 - (d * 10)});

svg.selectAll("text")
    .data(dataArray)
    .enter().append("text")
    .text(function(d) {return d;});
複製程式碼

當我們重新整理瀏覽器時,我們不會在頁面上看到任何文字,但我們會在DOM中再次看到它:

img

如果將滑鼠懸停在DOM中的文字行上,您將看到文字全部位於頁面頂部,其中X和Y等於0.我們將使用與我們相同的函式公式修改位置通過新增屬性用於矩形。

...
svg.selectAll("text")
    .data(dataArray)
    .enter().append("text")
    .text(function(d) {return d})
          .attr("x", function(d, i) {return (i * 60) + 25})
          .attr("y", function(d, i) {return 400 - (d * 10)});
複製程式碼

現在載入網頁時,您會看到浮動在條形圖上方的數字。

img

值得注意的是,因為這是SVG而不是影象,所以您可以選擇文字,就像在頁面上看到的任何其他文字一樣。

從這裡開始,您可以通過修改函式公式來重新定位數字。您可能希望將它們懸浮在條形圖上方,例如:

...
svg.selectAll("text")
    .data(dataArray)
    .enter().append("text")
    .text(function(d) {return d})
          .attr("x", function(d, i) {return (i * 60) + 36})
          .attr("y", function(d, i) {return 390 - (d * 10)});
複製程式碼

或者,您可以通過根據Y軸修改它們的位置,使數字浮動在矩形上。我們還想讓它更具可讀性,所以讓我們新增一個我們可以從style.css檔案中訪問的類。

...
.text {
  fill: white;
  font-family: sans-serif
}
複製程式碼

img

您可以通過定位和樣式儘可能多地修改文字。例如,您可能還想更改style.css檔案中的font-size屬性。

完成的程式碼和程式碼改進

此時,您應該擁有一個在JavaScript的D3庫中呈現的功能完備的條形圖。讓我們看看我們所有的程式碼檔案。

barchart.html
複製程式碼
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Bar Chart</title>

    <!-- Reference style.css -->
    <link rel = "stylesheet" type="text/css" href="style.css">

    <!-- Reference minified version of D3 -->
    <script type="text/javascript" src="d3.min.js"></script>
  </head>

  <body>
    <script type="text/javascript" src="barchart.js"></script>
  </body>
</html>
複製程式碼
style.css
複製程式碼
html, body {
  margin: 0;
  height: 100%
}

/*Rectangle bar class styling*/

.bar {
  fill: #0080FF
}

.bar:hover {
  fill: #003366
}

/*Text class styling*/

.text {
  fill: white;
  font-family: sans-serif
}
複製程式碼
barchart.js
複製程式碼
// Create data array of values to visualize
var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];

// Create variable for the SVG
var svg = d3.select("body").append("svg")
          .attr("height","100%")
          .attr("width","100%");

// Select, append to SVG, and add attributes to rectangles for bar chart
svg.selectAll("rect")
    .data(dataArray)
    .enter().append("rect")
          .attr("class", "bar")
          .attr("height", function(d, i) {return (d * 10)})
          .attr("width","40")
          .attr("x", function(d, i) {return (i * 60) + 25})
          .attr("y", function(d, i) {return 400 - (d * 10)});

// Select, append to SVG, and add attributes to text
svg.selectAll("text")
    .data(dataArray)
    .enter().append("text")
    .text(function(d) {return d})
           .attr("class", "text")
           .attr("x", function(d, i) {return (i * 60) + 36})
           .attr("y", function(d, i) {return 415 - (d * 10)});
複製程式碼

此程式碼完全正常,但您可以做很多事情來改進程式碼。例如,您可以利用SVG組元素將SVG元素組合在一起,從而允許您在更少的程式碼行中修改文字和矩形。

您還可以通過不同方式訪問資料。我們使用陣列來儲存我們的資料,但您可能希望視覺化您已有權訪問的資料,並且它可能比陣列中的資料要多得多。D3將允許您使用幾種不同的資料檔案型別:

  • HTML
  • JSON
  • 純文字
  • CSV(逗號分隔值)
  • TSV(製表符分隔值)
  • XML

例如,您可以在網站的目錄中擁有一個JSON檔案,並將其連線到JavaScript檔案

d3.json("myData.json", function(json) {
// code for D3 charts in here
});
複製程式碼

您還可以將D3庫與您可能已經從vanilla JavaScript中瞭解的其他互動式功能相結合。

結論

本教程通過在JavaScriptD3庫中建立條形圖。您可以通過訪問GitHub上D3 API來了解有關d3.js的更多資訊。更多前端教程請前往騰訊雲+社群學習更多知識。


參考文獻:《Getting Started with Data Visualization Using JavaScript and the D3 Library 》

問答

騰訊雲伺服器?

相關閱讀

教你從0到1搭建小程式音視訊

教你快速搭建一場釋出會直播方案

移形換影 - 短視訊色彩特效背後的故事

此文已由作者授權騰訊雲+社群釋出,原文連結:cloud.tencent.com/developer/a…

歡迎大家前往騰訊雲+社群或關注雲加社群微信公眾號(QcloudCommunity),第一時間獲取更多海量技術實踐乾貨哦~

海量技術實踐經驗,盡在雲加社群! cloud.tencent.com/developer?f…

相關文章