d3.js讀書筆記-2

 比例尺

比例尺基本內容

比例尺是一組把輸入域映射爲輸出範圍的函數。任意數據集中的值不可能剛好與圖表中的像素尺度一一對應。比例尺就是把這些數據值映射爲可視化圖形中使用的新值的便捷手段。D3的比例尺就是那些你定義的帶有參數的函數。定義好以後,就能夠調用這些比例尺函數,傳入值,它們就能返回按比例生成的輸出值。
比例尺的輸入值域(input domain)指可能的輸入值的範圍。
比例尺的輸出範圍(output range)指輸出值可能的範圍,通常以用於顯示的像素爲 單位。
其實比例尺就是歸一化的概念。
D3有一個比例尺函數生成器,經過d3.scale來訪問。要生成一個比例尺,在d3.scale後面加上要建立的比例尺類型便可。
var scale = d3.scale.linear();
設置比例尺的值域須要調用domain()方法,並將值域以數組形式傳給它。假設值域是100到500,那麼就能夠這樣寫代碼: 
scale.domain([100, 500]);   
設定輸出範圍的方式相似,但要調用range()方法:
scale.range([10, 350]);
若是不想給值域設置固定的值,那能夠使用兩個方便的數組函數:d3.min()和 d3.max(),讓它們幫你動態分析數據集。
vardataset = [
[5, 20], [480, 90], [250, 50], [100, 33], [330, 95],
[410, 12], [475, 44], [25, 67], [85, 21], [220, 88]
];
d3.max(dataset, function(d) {
return d[0];
});
這個存取器函數是一個匿名函數,max()會把數組中的每一個元素(即這裏的d)交給它。存取器函數的目的是指定比較哪一個值。對咱們的數據集而言,須要比較x值, 也就是嵌套數組的第一個值,位置爲0。把咱們剛剛介紹的知識綜合起來,就能夠建立一個動態映射x軸值的比例尺函數:
varxScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[0]; })]) .range([0, 300]);

其它比例尺

除了線性(linear)比例尺,D3還內置了另外幾個比例尺方法。
sqrt 
平方根比例尺。
pow 
冪比例尺,適合值以指數級變化的數據集。
log 
對數比例尺。
quantize 
輸出範圍爲獨立的值的線性比例尺,適合想把數據分類的情形。
quantile 
與quantize相似,但輸入值域是獨立的值,適合已經對數據分類的情形。
ordinal 
使用非定量值(如類名)做爲輸出的序數比例尺,很是適合比較蘋果和桔子。
d3.scale.category10()  、d3.scale.category20()、d3.scale.category20b()和d3.scale.category20c()
可以輸出10到20種類別顏色的預設序數比例尺,很是方便。
d3.time.scale() 
針對日期和時間值的一個比例尺方法,能夠對日期刻度做特殊處理。 領略了比例尺的威力以後,該經過一些東西來表達它們了,經過什麼呢?對, 數軸!

數軸

設定數軸

與比例尺類似,D3的數軸實際上也是由你來定義參數的函數。但與比例尺不一樣的是,調用數軸函數並不會返回值,而是會生成數軸相關的可見元素,包括軸線、標籤和刻度。
使用d3.svg.axis()能夠建立通用的數軸函數:
var xAxis = d3.svg.axis();
要使用數軸,最起碼要告訴它基於什麼比例尺工做。在此,咱們把繪製散點圖時定義的xScale傳給它: 
xAxis.scale(xScale);
還能夠繼續設置 標籤相對數軸顯示在什麼地方。默認位置是底部,也就是標籤會出如今軸線下方。水平數軸的位置可 以在頂部也能夠在底部。而垂直數軸則要麼在左要麼在右: 
xAxis.orient("bottom");
把這些方法連綴在一行會更簡潔:
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
SVG中的其餘元素都生成以後再生成數軸,這樣數軸就能夠出如今「上面了。想要生成數軸還要調用xAxis函數將其插入到svg元素中。
svg.append("g")
.call(xAxis);
 前面的代碼首先引用了svg,即DOM中的SVG元素。而後,append()在 這個元素的末尾追加了一個新的g元素。在SVG標籤內,g元素就是一個分組(group)元素。 分組元素是不可見的,跟line、rect和circle不同,但它有兩大用途:一是能夠用來包含(或「組織」)其餘元素,好讓代碼看起來簡潔整齊;二是能夠對整個分組應用變換,從而影響到該組中全部元素(line、rect和 circle)的視覺表現。D3的call()函數會取得(好比剛纔代碼鏈中)傳遞過來的元素,而後再把它交給其餘函數。對咱們這例子而言,傳遞過來的元素就是新的分組元素g(雖然這個元素不是必需的,但鑑於數軸函數須要生成不少線條和數值,有了它就能夠把全部元素都封裝在一個分組對象內)。而call()接着把g交給了xAxis函數,也就是要 在g元素裏面生成數軸。
就該用到SVG變換(transform)了。只要添加一行代碼,就能夠把整個數軸分組平移到圖表下方: 
svg.append("g") .attr("class", "axis") 
.attr("transform", "translate(0," + (h - padding) + ")") .call(xAxis); 
新增的這行代碼在attr()中設置了g元素的屬性transform。SVG中的變換功 能很是強大,有多種不一樣的變換方式,包括縮放和旋轉。但咱們暫時只介紹平移 (translation)變換,它能夠把整個g分組向下移動必定距離。平移變換的語法很簡單,就是translate(x,y),其中x和y的含義都很是明確, 就是要把元素移動到的新位置的x和y座標。

優化刻度

數軸的刻度線(tick)是用來傳達信息的,但也不是越多越好,多過某個數量,刻度線反而會讓圖表顯得混亂。使用ticks()方法就能夠粗略地指定刻 度線的數量: 
varxAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(5); //粗略地設置刻度線的數量

一個簡單的散點圖

//svg的寬度和高度
   var w = 500;
   var h = 300;
   var padding = 30;
   //初始化數據點
   var dataset = [];
   var numDataPoints = 15;
   //x軸最大的數值
   var xRange = Math.random() * 1000;
   //y軸最大的數值
   var yRange = Math.random() * 1000;
   for (var i = 0; i < numDataPoints; i++) {
    var newNumber1 = Math.floor(Math.random() * xRange);
    var newNumber2 = Math.floor(Math.random() * yRange);
    dataset.push([newNumber1, newNumber2]);
   }
   //建立刻度尺
   var xScale = d3.scale.linear()
         .domain([0, d3.max(dataset, function(d) { return d[0]; })])
         .range([padding, w - padding * 2]);
   var yScale = d3.scale.linear()
         .domain([0, d3.max(dataset, function(d) { return d[1]; })])
         .range([h - padding, padding]);
   var rScale = d3.scale.linear()
         .domain([0, d3.max(dataset, function(d) { return d[1]; })])
         .range([2, 5]);
   //定義x軸
   var xAxis = d3.svg.axis()
         .scale(xScale)
         .orient("bottom")
         .ticks(5);
   //定義y軸
   var yAxis = d3.svg.axis()
         .scale(yScale)
         .orient("left")
         .ticks(5);
   //建立svg元素
   var svg = d3.select("body")
      .append("svg")
      .attr("width", w)
      .attr("height", h);
   //建立圓形
   svg.selectAll("circle")
      .data(dataset)
      .enter()
      .append("circle")
      .attr("cx", function(d) {
        return xScale(d[0]);
      })
      .attr("cy", function(d) {
        return yScale(d[1]);
      })
      .attr("r", function(d) {
        return rScale(d[1]);
      });
   //建立標籤
   svg.selectAll("text")
      .data(dataset)
      .enter()
      .append("text")
      .text(function(d) {
        return d[0] + "," + d[1];
      })
      .attr("x", function(d) {
        return xScale(d[0]);
      })
      .attr("y", function(d) {
        return yScale(d[1]);
      })
      .attr("font-family", "sans-serif")
      .attr("font-size", "11px")
      .attr("fill", "red");
   
   //將x軸追加到g元素中
   svg.append("g")
    .attr("class", "axis")
    .attr("transform", "translate(0," + (h - padding) + ")")
    .call(xAxis);
   
   //將y軸追加到g元素中
   svg.append("g")
    .attr("class", "axis")
    .attr("transform", "translate(" + padding + ",0)")
    .call(yAxis);
其中座標軸的css以下,這裏須要注意的是,座標軸是由text、line和path構成的:
.axis path,
   .axis line {
    fill: none;
    stroke: black;
    shape-rendering: crispEdges;
   }
   
   .axis text {
    font-family: sans-serif;
    font-size: 11px;
   }

最終效果以下圖所示:
相關文章
相關標籤/搜索