D3.js學習(一)


從今天開始我將和大家一起學習D3.js(Data-Driven Documents),由於國內關於D3的學習資料少之又少,所以我覺得很有必要把自己學習過程記錄下來,供同學們參考,如果文章有有哪些表達有錯誤的還希望同學們幫我指出來。當然了, 可以的話我希望大家都可以去看看英文資料(文章后面將列英文資源),畢竟那才是原汁原味的D3。 好了, 廢話到此,下面我們開始我們的學習之旅吧!

什么是D3.js?

一句話:D3.js是一個操縱數據的javascript庫!

 

從一個簡單的例子開始

學習一個新的東西其實很簡單,我們先來一個效果圖,然后我們再一條條改它的語句,對比呈現的效果來學習這條屬性的作用,好了,下面就是我們要做的:

image

看上去是不是挺復雜的呢?下面我們來看看他的源碼到底是怎樣的呢?

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Simple Graph</title>
    <style type = "text/css">
    body{ font: 12px Arial;}
    path{
        stroke: steelblue;
        stroke-width: 2;
        fill: none;
    }
    .axis path,
    .axis line{
        fill: none;
        stroke: grey;
        stroke-width: 1;
        shape-rendering: crispEdges;
    }
    </style>
    <script type="text/javascript" src="script/d3.v3.js"></script>
</head>
<body>
    
    <script type="text/javascript">
    var margin = {top:30, right:20, bottom: 30, left: 50};
    width = 600 - margin.left -margin.right;
    height = 270 - margin.top - margin.bottom;
 
    var parseDate = d3.time.format("%d-%b-%y").parse;
 
    var x = d3.time.scale().range([0, width]);
    var y = d3.scale.linear().range([height, 0]);
 
    var xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(5);
    var yAxis = d3.svg.axis().scale(y).orient("left").ticks(5);
 
    //?
    var valueline = d3.svg.line()
        .x(function(d){return x(d.date);})
        .y(function(d){return y(d.close);});
 
    var svg = d3.select("body")
        .append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
        .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
 
    //Get the data
    d3.tsv("data/data.tsv", function(error, data){
        data.forEach(function(d){
            d.date = parseDate(d.date);
            d.close = +d.close;
        });
 
        //Scale(規模) the range of the data
        x.domain(d3.extent(data, function(d){
            return d.date;
        }));
        y.domain([0, d3.max(data, function(d){
            return d.close;
        })]);
 
        //Add the valueline path
        svg.append("path")
            .attr("d", valueline(data));
 
        //Add the X Axis
        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);
        //Add the Y Axis
        svg.append("g")
            .attr("class", "y axis")
            .call(yAxis);
    });
 
    </script>
</body>
</html>

看上去是不是很復雜的樣子,不要怕,下面我們對他進行一塊一塊的解剖微笑

 

HTML

上面的代碼包括樣式和腳本兩個部分,他的結構可以簡化為:

<!DOCTYPE html>
<meta charset="utf-8">
<style>
    The CSS 部分
</style>
<body>
<script type="text/javascript" src="d3/d3.v3.js"></script>
<script>
    The D3 JavaScript code is here
</script>
</body>

 

CSS

css部分主要是對元素設定樣式,上面圖表的CSS樣式為

body{ font: 12px Arial;}
path{
    stroke: steelblue;
    stroke-width: 2;
    fill: none;
}
.axis path,
.axis line{
    fill: none;
    stroke: grey;
    stroke-width: 1;
    shape-rendering: crispEdges;
}

 

我們可以改變其中的樣式來改變圖表的顯示效果,比方說設置path{ stroke: red ; …}則效果曲線將變成紅色

image

同樣的,如果我更改fill為red,我們將得到紅色的填充

image

其中"shape-rendering”是形狀渲染屬性,他一共有四個屬性,值為“crispEdges”表示該形狀將平滑顯示。跟多的屬性請同學學習SVG教程

 

D3 JavaScript

  • 設置邊距和圖表大小。 我們設定畫布的大小為:width:600,height:270,用一個margin對象來存儲圖表的邊距信息,計算出圖表的寬度和高度
    var margin = {top: 30, right: 20, bottom: 30, left: 50},
    width = 600 - margin.left - margin.right,
    height = 270 - margin.top - margin.bottom;
  • 下面我們先來看獲取數據的方法
    //Get the data
        d3.tsv("data/data.tsv", function(error, data){
            data.forEach(function(d){
                d.date = parseDate(d.date);
                d.close = +d.close;
            });
 這里我們是從data.tsv這個文件中獲取數據的,所謂tsv文件,簡單來說就是用tab空格把數據分割開來的一種數據格式,比方說我們的data.tsv文件的部分數據就是這樣的
date    close
1-May-12    58.13
30-Apr-12    53.98
27-Apr-12    67.00
當然了,D3允許導入的數據不僅僅只是這一種文件格式,他支持的數據格式可以為:

text: A plain old piece of text that has options to be encoded in a particular way

json: This is the afore mentioned JavaScript Object Notation.
xml: Extensible Markup Language is a language that is widely used for encoding documents in a human readable forrm.
html: HyperText Markup Language is the language used for displaying web pages.
csv: Comma Separated Values is a widely used format for storing data where plain text
information is separated by (wait for it) commas.
tsv: Tab Separated Values is a widely used format for storing data where plain text
information is separated by a tab-stop character.

 

data.forEach(function(d){

上面這一行代碼可以看做把數據分成了一行一行的形式,其中,每一行當中都有一個date和close值,並對沒一行數據執行下面的處理:

d.date = parseDate(d.date); --將d.date數據用前面定義的parseDate方法來格式化,將結果返回給d.date

d.close = +d.close; --將d.close轉化為一個數字

var parseDate = d3.time.format("%d-%b-%y").parse;
format()的格式有很多,我們可以根據自己的需要來設定自己的個格式,當然這里的格式要與文檔數據中的格式對應哦,不過現在我遇到的問題是,如何讓時間顯示為中文?如果有同學知道,請告訴我,我將非常感謝!
  • 設置橫軸方向和縱軸方向的區域(Domains)和范圍(Ranges)
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
這段代碼是為了讓我們導入的數據與圖表的大小相適應,range知道是圖表范圍的大小,他是一個尺寸大小。這段代碼告訴D3我們要畫些東西在x軸上,這些東西是時間/日期的一個實體。
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.close; })]);
而domain指的是數據的區域,extent返回的是最小的date到最大的date這樣一個跨度,所以,最小的date就對應於上面range的最小值0,我們可以用一幅圖來形象的表達:

image
 
  • 設置坐標軸
下面我們來分析這里幾行代碼:
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
坐標軸axis初始化方法通過d3.svg.axis()來調用,然后調用.scale(x)用前面定義的x來給坐標軸設定刻度, .orient()設定刻度相對坐標軸的位置,.ticks()告訴D3在坐標軸上設定差不多幾個刻度就夠了,比方說你要D3給你的X軸設定大概10個刻度:var xAxis = d3.svg.axis().scale(x).orient(“bottom”).ticks(10),效果如下
image
  • 為line()畫線函數添加數據
var valueline = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
關於Line函數的使用可以參照這里
  • 添加畫布
var svg = d3.select("body")
.append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
.append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"
);
d3.select(“body”)選擇body元素,然后在body里面增加一個子元素”svg”,給這個svg設定一些屬性,再往“svg”中添加一個”g”元素並設定一些屬性。
 
  • 開始畫東西啦
svg.append("path") // Add the valueline path.
    .attr("d", valueline(data));
我們再剛才創建的svg中添加一個 path路徑,讓后用前面的定義的 valueline來繪制一條路徑。然后我們再來繪制x軸和y軸
svg.append("g") // Add the X Axis
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);
svg.append("g") // Add the Y Axis
    .attr("class", "y axis")
    .call(yAxis);
兩個部分最后的.call()函數來定義前面的坐標軸初始化的方法來繪制坐標軸。

OK!,到目前為止我們的目標已經達到了,最開始要達到的效果我們已經實現,但是還有很多東西我們還沒有學會,比方說坐標軸的標簽? 好吧,下一節我們再來給坐標軸添加標簽!微笑

 

 

相關資料:

http://d3js.org/
http://bost.ocks.org/mike/
https://github.com/mbostock/d3/wiki
https://groups.google.com/forum/?fromgroups#!forum/d3-js
http://stackoverflow.com/questions/tagged/d3.js
https://github.com/mbostock/d3/wiki/Gallery


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM