D3.js - 資料連線

資料連線是 D3.js 中的另一個重要概念。它與選擇一起使用,使我們能夠根據我們的資料集(一系列數值)操作 HTML 文件。預設情況下,D3.js 在其方法中為資料集提供最高優先順序,並且資料集中的每個項對應於 HTML 元素。本章詳細介紹了資料連線。

什麼是資料連線?

資料連線使我們能夠根據現有 HTML 文件中的資料集註入,修改和刪除元素(HTML 元素以及嵌入的 SVG 元素)。預設情況下,資料集中的每個資料項對應於文件中的元素(圖形)。

隨著資料集的變化,也可以輕鬆地操作相應的元素。資料連線在我們的資料和文件的圖形元素之間建立了一種緊密的關係。資料連線使得基於資料集的元素操作變得非常簡單和容易。

資料連線如何工作?

資料連線的主要目的是使用給定的資料集對映現有文件的元素。它根據給定的資料集建立文件的虛擬表示,並提供使用虛擬表示的方法。讓我們考慮一個簡單的資料集,如下所示。

[10, 20, 30, 25, 15]

資料集有五個專案,因此可以對映到文件的五個元素。讓我們使用選擇器的 selectAll() 方法和資料連線的 data() 方法將它對映到以下文件的 li 元素。

HTML

<ul id = "list">
   <li><li>
   <li></li>
</ul> 

D3.js 程式碼

d3.select("#list").selectAll("li").data([10, 20, 30, 25, 15]);

現在,文件中有五個虛擬元素。前兩個虛擬元素是文件中定義的兩個 li 元素,如下所示。

1. li - 10
2. li - 20

對於前兩個 li,我們可以使用所有選擇器的元素修改方法,如 attr()style()text() 等,如下所示。 ****

d3.select("#list").selectAll("li")
   .data([10, 20, 30, 25, 15])
   .text(function(d) { return d; });

text() 方法中的函式用於獲取 li 元素對映資料。這裡,d 表示第一個 li 元素為 10,第二個 li 元素為 20。

接下來的三個元素可以對映到任何元素,可以使用資料連線的 enter() 和 selector 的 append() 方法完成。 enter() 方法提供對剩餘資料的訪問(未對映到現有元素),append() 方法用於從相應資料建立新元素。讓我們為剩餘的資料項建立 li。資料如下 -

3. li - 30
4. li - 25
5. li - 15

建立新的 li 元素的程式碼如下 -

d3.select("#list").selectAll("li")
   .data([10, 20, 30, 25, 15])
   .text(function(d) { return "This is pre-existing element and the value is " + d; })
   .enter()
   .append("li")
   .text(function(d) 
      { return "This is dynamically created element and the value is " + d; });

資料連線提供了另一種稱為 exit() 的方法,用於處理從資料集中動態刪除的資料項,如下所示。

d3.selectAll("li")
   .data([10, 20, 30, 15])
   .exit()
   .remove()

在這裡,我們使用 exit()remove() 方法從資料集及其對應的 li 中刪除了第四個專案。

完整的程式碼如下 -

<!DOCTYPE html>
<html>
   <head>
      <script type = "text/javascript" src = "https://d3js.org/d3.v4.min.js"></script>
      <style>
         body { font-family: Arial; }
      </style>
   </head>

   <body>
      <ul id = "list">
         <li></li>
         <li></li>
      </ul>
        
      <input type = "button" name = "remove" value = "Remove fourth value" 
         onclick = "javascript:remove()" />
      
      <script>
         d3.select("#list").selectAll("li")
            .data([10, 20, 30, 25, 15])
            .text(function(d) 
               { return "This is pre-existing element and the value is " + d; })
            .enter()
            .append("li")
            .text(function(d) 
               { return "This is dynamically created element and the value is " + d; });
             
         function remove() {
            d3.selectAll("li")
            .data([10, 20, 30, 15])
            .exit()
            .remove()
         }
      </script>
   </body>
</html>

上述程式碼的結果如下 -

  • This is pre-existing element and the value is 10
  • This is pre-existing element and the value is 20
  • This is dynamically created element and the value is 30
  • This is dynamically created element and the value is 25
  • This is dynamically created element and the value is 15

資料連線方法

資料連線提供以下四種方法來處理資料集 -

  • datum()
  • data()
  • enter()
  • exit()

讓我們詳細介紹這些方法。

datum() 方法

datum() 方法用於為 HTML 文件中的單個元素設定值。一旦使用選擇器選擇元素,就會使用它。例如,我們可以使用 select() 方法選擇現有元素(p 標籤),然後使用 datum() 方法設定資料。設定資料後,我們可以更改所選元素的文字或新增新元素,並使用 datum() 方法設定的資料分配文字。

建立頁面“datajoin_datum.html”並新增以下程式碼 -

<!DOCTYPE html>
<html>
   <head>
      <script type = "text/javascript" src = "https://d3js.org/d3.v4.min.js"></script>
   </head>

   <body>
      <p></p>
      <div></div>
      <script>
         d3.select("p")
         .datum(50)
         .text(function(d) { 
            return "Used existing paragraph element and the data " + d + " is assigned."; 
         });
         
         d3.select("div")
         .datum(100)
         .append("p")
         .text(function(d) { 
            return "Created new paragraph element and the data " + d + " is assigned."; 
         });
      </script>
   </body>
</html>

上述程式碼的輸出如下。

Used existing paragraph element and the data 50 is assigned.

Created new paragraph element and the data 100 is assigned.

data() 方法

data() 方法用於將資料集分配給 HTML 文件中的元素集合。使用選擇器選擇 HTML 元素後使用它。在我們的列表示例中,我們使用它來設定 li 選擇器的資料集。

d3.select("#list").selectAll("li")
   .data([10, 20, 30, 25, 15]);

enter() 方法

enter() 方法輸出之前沒有圖形元素的資料項集。在我們的列表示例中,我們使用它來建立新的 li 元素。

d3.select("#list").selectAll("li")
   .data([10, 20, 30, 25, 15])
   .text(function(d) { return "This is pre-existing element and the value is " + d; })
   .enter()
   .append("li")
   .text(function(d) { return "This is dynamically created element and the value is " + d; });

exit() 方法

exit() 方法輸出不再存在資料的圖形元素集。在我們的列表示例中,我們使用它通過刪除資料集中的資料項來動態刪除其中一個 li 元素。

function remove() {
   d3.selectAll("li")
      .data([10, 20, 30, 15])
      .exit()
      .remove()
}

資料功能

在 DOM 操作章節中,我們瞭解了 D3.js 中的不同 DOM 操作方法,例如 **style()text() 等。這些函式中的每一個通常都以常量值作為引數。然而,在 Data join 的上下文中,它將匿名函式作為引數。此匿名函式獲取相應的資料和使用 data() 方法分配的資料集的索引。因此,將為繫結到 DOM 的每個資料值呼叫此匿名函式。考慮以下 text() 函式。

.text(function(d, i) {
   return d;
});

在此函式中,我們可以應用任何邏輯來運算元據。這些是匿名函式,意味著沒有與函式關聯的名稱。除了 data(d)index(i) 引數之外,我們可以使用 關鍵字訪問當前物件,如下所示 -

.text(function (d, i) {
   console.log(d); // the data element
   console.log(i); // the index element
   console.log(this); // the current DOM object
   return d;
});

請考慮以下示例。

<!DOCTYPE html>
<html>
   <head>
      <script type = "text/javascript" src = "https://d3js.org/d3.v4.min.js"></script>
      <style>
         body { font-family: Arial; }
      </style>
   </head>

   <body>
      <p></p>
      <p></p>
      <p></p>
      <script>
         var data = [1, 2, 3];
         var paragraph = d3.select("body")
         .selectAll("p")
         .data(data)
         .text(function (d, i) {
            console.log("d: " + d);
            console.log("i: " + i);
            console.log("this: " + this);
            return "The index is " + i + " and the data is " + d;
         });
      </script>
   </body>
</html>

上面的指令碼將生成以下結果 -

The index is 0 and the data is 1

The index is 1 and the data is 2

The index is 2 and the data is 3

在上面的例子中,引數 d 為你提供資料元素, i 為你提供陣列中的資料索引, this 是當前 DOM 元素的引用。在這種情況下,它是段落元素。請注意,我們在上面呼叫了 .data(data) 函式。 data() 函式為所選元素提供資料,在我們的例子中它是資料陣列。