前端數據可視化D3 ——(案例1)柱狀圖

從本篇博客開始,我將使用D3來完成一些基礎的demo,關於數據可視化方面的介紹我就不多說了,關於d3的簡單介紹:

D3 的全稱是(Data-Driven Documents),一個被數據驅動的文檔。聽名字有點抽象,說簡單一點,其實就是一個 JavaScript 的函數庫,主要是用來做數據可視化,將強大的可視化組件應用於需求中。

 查看這個系列的代碼前,請先熟悉一些d3基礎知識,關於基礎可移步至官網:

https://d3js.org/

 


首先我們先來看看,要實現的柱狀圖的效果:

簡單分析一下:

1.首先我們需要一張畫布。

2.柱體由長方形構成,並且高度由數據驅動顯示。

3.由於柱體的寬度和高度剛好近似鋪滿整個畫布,所以需要用到比例尺

4.柱體上有對應數據顯示,大於30的文字被標紅。


下面來看一些重要的代碼塊:

    //線性比例尺
    const linear = d3.scaleLinear()
      .domain([0, d3.max(datalist)])
      .range([2, 398])

    //序數比例尺
    const scaleBand = d3.scaleBand().domain(d3.range(0,datalist.length))
      .range([10, 490])
      .paddingInner(0.08)
      ;

上面是兩個比例尺,線性比例尺被用於柱體的高度相關,而序數比例尺被用於柱體的寬度相關。

(畫布的寬度是500,高度是400)

    container.selectAll('rect')
      .data(datalist)
      .enter()
      .append('rect')
      .classed('bar', true)
      .style('height', function (d, i) {
        return linear(d) - 20 + 'px';
      })
      .attr('x', function (d, i) {
        return scaleBand(i) 
      })
      .attr('width', function (d, i) {
        return scaleBand.bandwidth() + 'px'
      })
      .attr('y', function (d, i) {
        return 400 - linear(d) + 10;
      });

上面是添加柱體的代碼,用到了enter,表示有多少數據添加多少rect。另外柱體的高度、寬度、x軸、y軸座標都動態生成。

    container.selectAll('text').data(datalist)
      .enter()
      .append('text')
      .attr('text-anchor', 'middle')
      .text(function (d) {
        return d;
      })
      .attr('x', function (d, i) {
        return scaleBand(i) + scaleBand.bandwidth()/2 ;
      })
      .attr('y', function (d, i) {
        return 400 - linear(d) + 30;
      })
      .style('fill', function (d) {
        if (d > 30) {
          return 'red'
        }
      })

上面是添加數據文字的代碼塊,再次用到enter,其中文字顏色fill屬性也由函數動態生成,大於30的部分是紅色。


最後附上完整代碼:

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://d3js.org/d3.v5.min.js"></script>
  <style>
    #app {
      width: 500px;
      height: 400px;
      background: #efefef;
      position: relative;
    }

    .bar {
      /* width: 50px; */
      fill: green;
      position: absolute;
      bottom: 100px;
    }

    .bar span {
      display: block;
      text-align: center;
    }
  </style>
</head>

<body>
  <svg id="app">
  </svg>

  <script>

    var datalist = [10, 20, 30, 40, 50,60,70,80,90]

    //線性比例尺
    const linear = d3.scaleLinear()
      .domain([0, d3.max(datalist)])
      .range([2, 398])

    //序數比例尺
    const scaleBand = d3.scaleBand().domain(d3.range(0,datalist.length))
      .range([10, 490])
      .paddingInner(0.08)
      ;

    var container = d3.select("#app");

    container.selectAll('rect')
      .data(datalist)
      .enter()
      .append('rect')
      .classed('bar', true)
      .style('height', function (d, i) {
        return linear(d) - 20 + 'px';
      })
      .attr('x', function (d, i) {
        return scaleBand(i) 
      })
      .attr('width', function (d, i) {
        return scaleBand.bandwidth() + 'px'
      })
      .attr('y', function (d, i) {
        return 400 - linear(d) + 10;
      });


    container.selectAll('text').data(datalist)
      .enter()
      .append('text')
      .attr('text-anchor', 'middle')
      .text(function (d) {
        return d;
      })
      .attr('x', function (d, i) {
        return scaleBand(i) + scaleBand.bandwidth()/2 ;
      })
      .attr('y', function (d, i) {
        return 400 - linear(d) + 30;
      })
      .style('fill', function (d) {
        if (d > 30) {
          return 'red'
        }
      })




  </script>

</body>

</html>

 

有任何問題歡迎評論或者私信提出~看到後我都會回覆😊

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章