DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> 關於JavaScript >> D3.js實現直方圖的方法詳解
D3.js實現直方圖的方法詳解
編輯:關於JavaScript     

一、直方圖簡介

直方圖就是一種照片的分析方式,橫向代表亮度,縱向代表像素數量。首先分析出照片中所有像素的亮度,然後計算出具體數值,再把它們映射到橫軸上。這樣的話,越高,這個亮度上的像素就越多。

直方圖的觀看規則就是“左黑右白”,左邊代表暗部,右邊代表亮部,而中間則代表中間調。

縱向上的高度代表像素密集程度,越高,代表的就是分布在這個亮度上的像素很多。

直方圖用於描述概率分布,D3 提供了直方圖的布局 Histogram 用於轉換數據。


假設有數組 a = [10, 11, 11.5, 12.5, 13, 15, 19, 20 ],現在把10~20的數值范圍分為5段,即:

10~12, 12~14, 14~16, 16~18, 18~20

那麼數組 a 的各數值都落在這幾段區域的哪一部分呢?經過計算,可以知道,這5段分別具有的元素個數為:

3, 2, 1, 0 , 2

將這個用圖形展示出來的,就是直方圖。

好了,開始制作吧~

二、數據

首先生成隨機數據:

var rand = d3.random.normal(0,25); 
var dataset = []; 
for(var i=0;i<100;i++){ 
 dataset.push( rand() ); 
} 

d3.random.normal 生成一個函數,這個函數能夠按正態(高斯)分布隨機生成數值。要傳入兩個參數,第一個是位置參數,第二個是尺寸參數。關於正態分布的定義,可參見維基百科。將這個函數賦值給 rand 之後,接下來只要用 rand() 即可生成隨機數。

三、布局(數據轉換)

接下來,要將上述數據進行轉換,即確定一個區間和分隔數之後,另數組的數值落在各區域裡。先定義一個布局:

var bin_num = 15; 
var histogram = d3.layout.histogram() 
   .range([-50,50]) 
    .bins(bin_num) 
   .frequency(true); 

d3.layout.histogram: 直方圖的布局

range: 區間的范圍

bins: 分隔數

frequency: 若值為 true,則統計的是個數;若值為 false,則統計的是概率

接下來即可轉換數據:

var data = histogram(dataset); 

來看看轉換前後的數據有什麼分別吧。轉換前:

轉換後:


可以看到,轉換後的數組,長度即分隔數,每一個區間內有落到此區間的數值(圖中的0,1,2,...),數值的個數(length),還

有三個參數:

x: 區間的起始位置

dx: 區間的寬度

y: 落到此區間的數值的數量(如果 frequency 為 true);落到此區間的概率(如果 frequency 為 false)

四、繪制

繪制之前,需要定義一個比例尺,因為通常我們需要讓轉換後的 y 在希望的范圍內伸縮。

var max_height = 400; 
var rect_step = 30; 
var heights = []; 
for(var i=0;i<data.length;i++){ 
 heights.push( data[i].y ); 
} 
var yScale = d3.scale.linear() 
     .domain([d3.min(heights),d3.max(heights)]) 
     .range([0,max_height]); 

最後,繪制圖形:

//繪制圖形 
var graphics = svg.append("g") 
     .attr("transform","translate(30,20)"); 
 
//繪制矩形 
graphics.selectAll("rect") 
  .data(data) 
  .enter() 
  .append("rect") 
  .attr("x",function(d,i){ 
   return i * rect_step; 
  }) 
  .attr("y", function(d,i){ 
   return max_height - yScale(d.y); 
  }) 
  .attr("width", function(d,i){ 
   return rect_step - 2; 
  }) 
  .attr("height", function(d){ 
   return yScale(d.y); 
  }) 
  .attr("fill","steelblue"); 
 
//繪制坐標軸的直線 
graphics.append("line") 
  .attr("stroke","black") 
  .attr("stroke-width","1px") 
  .attr("x1",0) 
  .attr("y1",max_height) 
  .attr("x2",data.length * rect_step) 
  .attr("y2",max_height); 
 
//繪制坐標軸的分隔符直線 
graphics.selectAll(".linetick") 
  .data(data) 
  .enter() 
  .append("line") 
  .attr("stroke","black") 
  .attr("stroke-width","1px") 
  .attr("x1",function(d,i){ 
   return i * rect_step + rect_step/2; 
  }) 
  .attr("y1",max_height) 
  .attr("x2",function(d,i){ 
   return i * rect_step + rect_step/2; 
  }) 
  .attr("y2",max_height + 5); 
 
//繪制文字 
graphics.selectAll("text") 
  .data(data) 
  .enter() 
  .append("text") 
  .attr("font-size","10px") 
  .attr("x",function(d,i){ 
   return i * rect_step; 
  }) 
  .attr("y", function(d,i){ 
   return max_height; 
  }) 
  .attr("dx",rect_step/2 - 8) 
  .attr("dy","15px") 
  .text(function(d){ 
   return Math.floor(d.x); 
  }); 

五、總結

以上就是這篇文章的全部內容了,希望能對大家的學習或者工作帶來一定的幫助,如果有疑問大家可以留言交流。

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved