D3的一点理解

D3的一点理解

D3

用其官网的话来讲:html

D3.js is a JavaScript library for manipulating documents based on data. D3 helps you bring data to life using HTML, SVG, and CSS.

D3是一个用于数据可视化的JS库。其将数据与DOM绑定,经过创建数据与DOM元素样式之间的关系,来表现数据,实现可视化。它也是github上星第4多的JS库。node

不用工具绘制一个柱状图

成果图以下git

d301

代码以下github

<style>
    .chart div {
      font: 10px sans-serif;
      background-color: steelblue;
      text-align: right;
      padding: 3px;
      margin: 1px;
      color: white;
    }
  </style>
  ...
  <body>
  <div class="chart"></div>
  <script>
    let data = [30, 86, 168, 281, 303, 365]
    let chart = document.getElementsByClassName('chart')[0]
    data.forEach(d => {
      let div = document.createElement('div')
      div.style.width = `${d}px`
      div.textContent = d
      chart.appendChild(div)
    })
  </script>
</body>

整理思路以下

  1. 选择画布

    let chart = document.getElementsByClassName('chart')[0]app

  2. 建立元素,经过元素的样式来表现数据函数

    let div = document.createElement('div')
    div.style.width = `${d}px`
    div.textContent = d
  3. 将元素添加到画布上工具

    chart.appendChild(div)

用D3绘制一个柱状图

整个思路中,首先要注意数据与元素数量之间的关系ui

有多少组数据,就应该对应有多少个元素spa

其次就是创建数据与元素样式之间的函数关系双向绑定

例如数据与元素宽度之间的函数关系

function (data) {
  return data + "px";
}

数据与元素文本内容之间的函数关系

function (data) {
  return data;
}

我我的以为,d3的 Data-Driven Documents,主要体现就是以上两点

用d3实现一样效果以下

<script src="https://d3js.org/d3.v4.min.js"></script>
  <script>
    let data = [30, 86, 168, 281, 303, 365]
    d3.select(".chart") // 选择画布
      .selectAll("div") // 选择画布上的div元素
      .data(data) // 将画布上的div元素与数据绑定
      .enter().append("div") // 若是不够,补足
      .style("width", function (d) { // 数据与元素宽度之间的函数关系
        return d + "px";
      })
      .text(function (d) { // 数据与元素文本内容之间的函数关系
        return d;
      });
  </script>

理解数据与元素数量之间的关系

数据

let data = [30, 86, 168, 281, 303, 365]

自己就有对应数量的元素

若是在 .chart 中有对应数量的 div

<div class="chart">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
  </div>

那么就不须要额外添加 div 元素

d3.select(".chart")
      .selectAll("div")
      .data(data)
      .style("width", function (d) {
        return d + "px";
      })
      .text(function (d) {
        return d;
      });

自己就没有元素

若是没有 div 元素,就须要经过 enter().append('div') 来添加相应数量的元素

<div class="chart">
  </div>

其中 enter()

Returns the enter selection: placeholder nodes for each datum that had no corresponding DOM element in the selection. (The enter selection is empty for selections not returned by selection.data.)
d3.select(".chart")
      .selectAll("div")
      .data(data)
      .enter().append('div')
      .style("width", function (d) {
        return d + "px";
      })
      .text(function (d) {
        return d;
      })

自己有过多数量的元素

若是在 .chart 中有过多数量的 div

<div class="chart">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
  </div>

那么就须要将多余的 div 移除,经过 exit().remove() 来实现

其中 exit()

Returns the exit selection: existing DOM elements in the selection for which no new datum was found. (The exit selection is empty for selections not returned by selection.data.)
d3.select(".chart")
      .selectAll("div")
      .data(data)
      .style("width", function (d) {
        return d + "px";
      })
      .text(function (d) {
        return d;
      })
      .exit().remove()

更新数据与元素数量之间的关系

首先要知道在 d3 中,数据与 DOM 元素并非双向绑定的,在将数据绑定到元素以后,再次修改数据,元素并不会产生对应的变化

因此数据更新要手动完成

function update(data) {
      d3.select(".chart")
        .selectAll("div")
        .data(data)
        .style("width", function (d) {
          return d + "px";
        })
        .text(function (d) {
          return d;
        })
     // 若是元素不够,补足
      d3.select(".chart")
        .selectAll("div")
        .data(data)
        .enter().append('div')
        .style("width", function (d) {
          return d + "px";
        })
        .text(function (d) {
          return d;
        })
    // 若是元素多余,移除
      d3.select(".chart")
        .selectAll("div")
        .data(data)
        .exit().remove()
    }

完整实验代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>D3.js</title>
  <style>
    .chart div {
      font: 10px sans-serif;
      background-color: steelblue;
      text-align: right;
      padding: 3px;
      margin: 1px;
      color: white;
    }
  </style>
</head>

<body>
  <div class="chart">
  </div>
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <script>
    let data = [30, 86, 168, 281, 303, 365]
    d3.select(".chart")
      .selectAll("div")
      .data(data)
      .enter().append('div')
      .style("width", function (d) {
        return d + "px";
      })
      .text(function (d) {
        return d;
      })

    setTimeout(function () {
      data = [30, 86, 168, 281, 303, 365, 700]
      update(data)
    }, 1000)

    function update(data) {
      d3.select(".chart")
        .selectAll("div")
        .data(data)
        .style("width", function (d) {
          return d + "px";
        })
        .text(function (d) {
          return d;
        })

      d3.select(".chart")
        .selectAll("div")
        .data(data)
        .enter().append('div')
        .style("width", function (d) {
          return d + "px";
        })
        .text(function (d) {
          return d;
        })

      d3.select(".chart")
        .selectAll("div")
        .data(data)
        .exit().remove()
    }
  </script>
</body>

</html>

小结

d3提供的选择方法,能处理数据与元素数量不匹配的状况

  • 当元素数量不够时,经过enter()能选择到那些用于补足的元素
  • 当元素数量过多时,经过exit()能选择那些过剩的元素

d3方便了经过元素的样式来展示数据的过程,用户本身定义数据与元素样式之间的函数关系

相关文章
相关标签/搜索