背景及相關簡介
在最近的BS新項目中需要用到繪圖數據顯示的功能。在進行充足的選擇之后決定才去開源的Flot。Flot是一個jQuery繪圖庫。主要用於簡單的繪制圖表功能。具有吸引人的渲染外觀和互操作的特性。其在Internet Explorer 6+, Chrome, Firefox 2+, Safari 3+ and Opera 9.5+瀏覽器下工作正常。目前的版本是Version0.8.3. 以下是相關鏈接。在官網的example中展示出了flot可以繪制的樣例,並且我想這些樣例的源代碼也許是大家如何學習flot的最快的方法吧。嘿嘿。這里有一點要注意的地方: 在文檔中都用plot來代替Flot,作者給出了回答瞬間無語。
What's with the name?
First: it's pronounced with a short o, like "plot". Not like "flawed".
So "Flot" rhymes with "plot".
And if you look up "flot" in a Danish-to-English dictionary, some of the words that come up are "good-looking", "attractive", "stylish", "smart", "impressive", "extravagant". One of the main goals with Flot is pretty looks.
內容
安裝
和其他jquery庫一樣,我們只需要在html文檔的末尾的jquery庫的后面引入即可。這里要注意的是我們的瀏覽器必須支持HTML5 canvas標簽。為了兼容IE9。我們可以使用canvas模擬庫Excanvas來實現。我們在官網的demo中也可以發現如下的引入方式。
1 <!--[if lte IE 8]><script language="javascript" type="text/javascript" src="excanvas.min.js"></script><![endif]-->
在這里要說明IE6是不被支持的。Excanvas實現仿真繪圖的原理是依賴VML矢量標記語言。另外我們也可以嘗試着使用Flashcanvas庫來通過Flash實現仿真。盡管Flash對比VML加載起來會顯得慢一點,但是當在繪制很多點的圖時,Flash版本在整體的加載上會更加的快。在jquery庫的要求上至少是需要jquery1.2.6。
基本使用 placeholder
創建一個占位div來放置繪出來的圖:
1 <div id="placeholder"></div>
在這里我們只需要簡單的設置div的id,plot將會修改很多屬性來呈現繪制的圖像。我們無需自己設置該div的樣式,比如在IE7下如果設置該div的背景圖就會引發問題。
然后我們需要設置placeholder的高度和寬度,因為plot庫不知道如何繪制圖的大小。這里我們采取直接在html中定義css:
1 <div id="placeholder" style="width:600px;height:300px"></div>
同時你也可以在外部的stylesheet中定義大小,確保該div placeholder沒有被display:none來標記,這樣可能會導致混亂的結果。
然后在js中運行如下方法:
1 var plot = $.plot(placeholder, data, options)
我們來看看這三個參數和plot對象
- placeholder:繪圖要放置的div區域,為jquery對象或者DOM對象。
- data: 繪圖需要的數據集合,為一個數組
- options: 自定義繪圖的設置
- plot: 該對象提供了一些方法來給我們使用返回值
這里是一個簡單的例子:
1 $.plot($("#placeholder"), [ [[0, 0], [1, 1]] ], { yaxis: { max: 1 } });
數據格式 data
[series1, series2, ...]
這一系列的數據即可是原始的二維坐標點數組(內部x和y值必須為數字--我們在從數據庫檢索出數據序列化為JSON提交至前台時要注意數據格式,如果發生一些神秘錯誤請確保你的輸入數據為數字類型而不是字符串類型),也可以是一個對象的屬性。
當輸入進去的坐標值為空或者不能轉換成為數字,那么該數據點就不予以繪制出。存在一個特殊的例子即如果繪制一條線時遇到坐標為空的點則該點將成為這條繪制線的截至點。后面的點將不能和前面的點相連。我們可以指定第三個坐標值來設置繪制線或者柵欄下方填充的面積值(默認是0);

1 var d1 = []; 2 for (var i = 0; i < 14; i += 0.5) { 3 d1.push([i, Math.sin(i)]); 4 } 5 6 var d2 = [[0, 3], [4, 8], [8, 5], [9, 13]]; 7 8 // A null signifies separate line segments 9 10 var d3 = [[0, 12], [7, 12], null, [7, 2.5], [12, 2.5]]; 11 12 $.plot("#placeholder", [ d1, d2, d3 ]);
得到的效果是這樣的
紅線處存在斷截。
對於數據為對象類型時應當滿足如下格式內容:
1 { 2 color: color or number 3 data: rawdata 4 label: string 5 lines: specific lines options 6 bars: specific bars options 7 points: specific points options 8 xaxis: number 9 yaxis: number 10 clickable: boolean 11 hoverable: boolean 12 shadowSize: number 13 highlightColor: color or number 14 }
下面我來一一介紹以上的屬性:
color: 繪制出來的圖中線條或者柱狀的顏色,如果不指定將自動生成格式為CSS color規則的顏色值。
data: 為繪制的坐標點的值。
label: 用來指示圖中該段數據對應的名字,如“Line1”。
lines: 設置如果繪圖為折線圖時的相關屬性,如show, fill, fillColor等
bars: 設置如何繪圖為柱狀圖時的相關屬性, 如show, fill, fillColor等
points: 設置繪圖中的每個點的相關屬性,如形狀(默認為circle)還有半徑大小
xaxis, yaxis: 這兩屬性的意思是對應的該條折線或者柱子所采用的坐標軸,默認為一,如果不設定則所有的數據都采用相同一個坐標軸,如果設置其他值(2~n)則采用圖像上顯示的第n個坐標軸顯示。如下圖所示:
(d2采用的坐標軸為外圍的坐標軸)
clickable, hoverable: 用來設置互操作的屬性,取值為bool類型。類似事件機制。false則靜止該點的互操作功能。
shadowSize: 該段線條的陰影大小。為阿拉伯數字
highlightColor: 選擇高亮的顏色。
每個字段都存在一個默認值。如果我們對其需要的屬性進行再賦值則覆蓋掉默認值如:
1 [ { label: "Foo", data: [ [10, 1], [17, -14], [30, 5] ] }, { label: "Bar", data: [ [11, 13], [19, 11], [30, -7] ] } ]
如下是數據為對象時的例子:(options設置為空)

1 ar d1 = []; 2 for (var i = 0; i < 14; i += 0.5) { 3 d1.push([i, Math.sin(i)]); 4 } 5 6 var d2 = [[0, 3], [4, 8], [8, 5], [9, 13]]; 7 8 var d3 = []; 9 for (var i = 0; i < 14; i += 0.5) { 10 d3.push([i, Math.cos(i)]); 11 } 12 13 var d4 = []; 14 for (var i = 0; i < 14; i += 0.1) { 15 d4.push([i, Math.sqrt(i * 10)]); 16 } 17 18 var d5 = []; 19 for (var i = 0; i < 14; i += 0.5) { 20 d5.push([i, Math.sqrt(i)]); 21 } 22 23 var d6 = []; 24 for (var i = 0; i < 14; i += 0.5 + Math.random()) { 25 d6.push([i, Math.sqrt(2*i + Math.sin(i) + 5)]); 26 } 27 28 $.plot("#placeholder", [{ 29 data: d1, 30 lines: { show: true, fill: true } 31 }, { 32 data: d2, 33 bars: { show: true } 34 }, { 35 data: d3, 36 points: { show: true } 37 }, { 38 data: d4, 39 lines: { show: true } 40 }, { 41 data: d5, 42 lines: { show: true }, 43 points: { show: true } 44 }, { 45 data: d6, 46 lines: { show: true, steps: true } 47 }]);
注意:我們即可以在每個data集合中單獨的設置以上的屬性來實現每個折線或者條形柱的不同之處,同時也可以在option的統一設置中來集體設置以上相關屬性。
Options
所有的選項都是完全可選擇的,我們可以單獨的在文檔中定義option對象,然后在$.plot方法中傳入option值:
1 var options = { 2 series: { 3 lines: { show: true }, 4 points: { show: true } 5 } 6 }; 7 8 $.plot(placeholder, data, options);
在options內部有很多屬性。以下我們一一來說明:
定制 legend屬性
legend屬性是來定義折線圖的label標簽信息屬性
1 legend: { 2 show: boolean 3 labelFormatter: null or (fn: string, series object -> string) 4 labelBoxBorderColor: color 5 noColumns: number 6 position: "ne" or "nw" or "se" or "sw" 7 margin: number of pixels or [x margin, y margin] 8 backgroundColor: null or color 9 backgroundOpacity: number between 0 and 1 10 container: null or jQuery object/DOM element/jQuery expression 11 sorted: null/false, true, "ascending", "descending", "reverse", or a comparator 12 }
show:設置是否顯示該label,
labelFormatter: 設置點擊該label對應的事件。舉例如下:
labelFormatter: function(label, series){ //alert(label); return '<a href="#' + label + '">' + label + '</a>'; }
labelBoxBorderColor: 設置label的邊框顏色。
noColumns: 設定圖中的label組排成多少列,默認為1.則表明每行只排列一個label.設置為n則每行排列n個label. 如下是noColumns:2的情況。
Position: 有4個選項"ne", "nw", "se", "sw"分別表示將label組顯示在 ↗, ↖, ↘, ↙。
margin: 設置其與繪圖div邊緣的距離,可以像素值表示,也可用[x margin, y margin]表示。 如[50,50]
backgroundColor與backgroundOpacity:設置label塊的背景顏色顏色值。默認是透明色。
container:
sorted: 允許設置為null/false/true/"ascending"/"descending"/"reverse"/function(). 默認label的排序是通過默認的series數組內部的序列號來排序的。如上d2的data在d1的data前push進數組,所以d2顯示在前面。"reverse":顛倒默認的排序。 "descending": 按照label名字降序排列。true&"ascending":按照label的名字的升序排列。 false&null: 按照默認排列。同時我們還能自定義排序內部比較方法通過傳遞兩個data對象來對比其label或者color.如下是一個例子:看過排序算法的應該理解不多說了。
1 sorted: function(a, b) { 2 // sort alphabetically in ascending order 3 return a.label == b.label ? 0 : ( 4 a.label > b.label ? 1 : -1 5 ) 6 }
定制化 axes

1 xaxis, yaxis: { 2 show: null or true/false 3 position: "bottom" or "top" or "left" or "right" 4 mode: null or "time" ("time" requires jquery.flot.time.js plugin) 5 timezone: null, "browser" or timezone (only makes sense for mode: "time") 6 7 color: null or color spec 8 tickColor: null or color spec 9 font: null or font spec object 10 11 min: null or number 12 max: null or number 13 autoscaleMargin: null or number 14 15 transform: null or fn: number -> number 16 inverseTransform: null or fn: number -> number 17 18 ticks: null or number or ticks array or (fn: axis -> ticks array) 19 tickSize: number or array 20 minTickSize: number or array 21 tickFormatter: (fn: number, object -> string) or string 22 tickDecimals: null or number 23 24 labelWidth: null or number 25 labelHeight: null or number 26 reserveSpace: null or true 27 28 tickLength: null or number 29 30 alignTicksWithAxis: null or number 31 }
以上的屬性是用來設置坐標軸相關。x軸和Y軸通用。我來一一解釋:
show: 取值為bool 是否顯示坐標軸。默認值為true.
position: 設置坐標軸所處圖的位置。x軸取值"top" / "bottom", y軸取值"left" / "right"。
mode: 設置對應的數值應該如何解析。默認值或者null值則認為對應的數值用小數來解析, 設置"time" 來解析時間戳類型的數值(需要引入jquery.flot.time.js插件來支持時間戳轉換)
timezone: 設置時區。取值有null、"browser",或者具體的時區設置。
color: 設置坐標線的顏色
tickColor:設置坐標線的顏色。貌似和上者一樣。官網說可以得到更加有細密紋路的控制。
font:設置坐標軸上的值的字體樣式,如下所示:
1 { 2 size: 11, 3 lineHeight: 13, 4 style: "italic", 5 weight: "bold", 6 family: "sans-serif", 7 variant: "small-caps", 8 color: "#545454" 9 }
在這里size和lineHeight屬性必須用像素值定義。
min && max: 設定坐標軸的最大值和最小值。如果未設定則選擇繪圖數據源中的最大值和最小值。
autoscaleMargin:此屬性用在未指定坐標軸最大值和最小值的時候來指定該坐標軸最大的延伸值(感覺就是在壓縮或者放大圖)。x軸的默認值為null,y軸的默認值為0.02這樣能夠適應大部分用例的正常大小。
transform & inverseTransForm: 設置更改你繪圖出來的數值。例如原始值需要做一些壓縮或者擴張(eg.需要對小數值轉換為百分數的時候)。接受的值為function.其大致運行過程是當Flot開始繪圖時,每一個data源首先通過該轉換函數。如下例子:x 坐標軸的值轉換成為自然對數:
1 xaxis: { 2 transform: function (v) { return Math.log(v); }, 3 inverseTransform: function (v) { return Math.exp(v); } 4 }
inverseTransform是transform方法的反方法。 v == inverseTransform(transform(v))。這個方法在轉換canvas坐標為數據原始坐標是需要用到的。前提是你如果想使用互操作功能的話。假如你點擊一個點想得到該點的原始數據。你就需要該轉換方法來還原canvas坐標為原始坐標。
ticks: 在英語中為十字叉的意思。在這里我們可以理解為網格線的起點坐標。前面我們可以設置ticks的顏色。這里是設置ticks的具體屬性。為何我們不設置時繪制出來的圖能夠恰如其分的生成適當數量的坐標線來美化圖呢。這是因為tick 生成器算法來完成的,這個算法有兩個步驟,首先算法根據數據的max和min來估算需要多少條ticks然后根據這個數量計算出一個能夠很好的均分ticks的間隔大小。然后再生成ticks. 如下兩張圖前者是沒有設置tick時系統自動生成(0.0~15.0)均等分割的7條tick。而后者是通過設置ticks: [[0, "zero"], [5, "one mark"], [10, "two marks"]]來顯示3條ticks.
這里需要注意的是ticks可接受的值如下:
- 數值: 我們可自行指定算法根據data源來生成多少條ticks,但是盡管你設置了數值假如為3,算法也會盡量去滿足你的要求去生成適合的ticks數量,如果5條更加適合的話算法就會生成5條。
- 0: 如果你不想顯示任何的ticks, 你可以設置為0或者一個空的數組[].
- 數組: 如果你想完全的覆蓋 tick生成算法, 你可以給ticks指定任何的數組來綁定ticks.我們可以通過string來定制顯示該tick.
ticks: [[0, "zero"], [5, "one mark"], [10, "two marks"]]
- function: 我們可以靈活的指定tick生成方法來通過其數組的返回值設定ticks。如下例子是通過方法的返回值來設置pi的倍數的ticks。
1 function piTickGenerator(axis) { 2 var res = [], i = Math.floor(axis.min / Math.PI); 3 do { 4 var v = i * Math.PI; 5 res.push([v, i + "\u03c0"]); 6 ++i; 7 } while (v < axis.max); 8 return res; 9 }
tickSize: 如果你希望跳過算法自動計算的間隔來手動設置tick的間隔大小。你可以設置該屬性。如上圖的算法設置的間隔為2.5,我在此處設置tickSize: 5, 則得到如下圖
minTickSize: 如果你想設置一個不確定的tick的大小的話,可以設置這個屬性。
tickFormatter: 設置tick的格式。可接受function或者string。function(val, axis)接受兩個參數為tick值和axis坐標對象(該對象中保存着從數據源收集來的最大值和最小值等),返回string類型。默認的格式化器為:
function formatter(val, axis) { return val.toFixed(axis.tickDecimals); }
這里有一個定制化的格式化器:
1 function suffixFormatter(val, axis) { 2 if (val > 1000000) 3 return (val / 1000000).toFixed(axis.tickDecimals) + " MB"; 4 else if (val > 1000) 5 return (val / 1000).toFixed(axis.tickDecimals) + " kB"; 6 else 7 return val.toFixed(axis.tickDecimals) + " B"; 8 }
tickDecimals: 設置tick的數值的小數點位數。為number。
labelWidth & labelHeight: 設置tick中label的大小
reserveSpace:
tickLength: 設置tick線的長度。默認ticks長度延伸到整個plot, 設置0為則完全的隱藏線條。
alignTicksWithAxis: 當設置折線圖相同軸的坐標軸不止一條時,設置該屬性可以美化數據對應的外觀,設置為1,當你存在一條Y軸在左邊另外一條在右邊時,網格線可以自動的匹配他們對應的數值。
Multiple Axes
如果你需要不止一條x軸或者y軸來顯示數據(如在data屬性中設置yaxis: 2),你需要指定圖中每條data對應使用的坐標軸。在這里我們通過xaxes:[] & yaxes: []來設置。
定制化Grid

1 grid: { 2 show: boolean 3 aboveData: boolean 4 color: color 5 backgroundColor: color/gradient or null 6 margin: number or margin object 7 labelMargin: number 8 axisMargin: number 9 markings: array of markings or (fn: axes -> array of markings) 10 borderWidth: number or object with "top", "right", "bottom" and "left" properties with different widths 11 borderColor: color or null or object with "top", "right", "bottom" and "left" properties with different colors 12 minBorderMargin: number or null 13 clickable: boolean 14 hoverable: boolean 15 autoHighlight: boolean 16 mouseActiveRadius: number 17 } 18 19 interaction: { 20 redrawOverlayInterval: number or -1 21 }
網格是圖的基本架構,我們可以在grid屬性中設置更多的參數。
show: boolean. 設置為false時繪制的圖不顯示網格,ticks也不顯示。
aboveData: 如果設置為true, 則網格線處於圖的上方。
color: 設置網格的顏色。
backgroundColor: 設置網格的背景色。
margin: {top: pixels, bottom:pixels, left: pixels, right: pixels}設置圖對於placeholder的外邊距值。
labelMargin: 設置tick的label和坐標線的空間,取值為pixels.
axisMargin: 當我們設置兩條同軸的坐標軸在同一邊時設置其之間的邊距。
markings: 數組值或者方法。用來在plot的背景中繪畫出簡單的線條或者矩形,你可以指定數組來規定x軸和y軸的范圍{xaxis: {from, to}, yaxis{from, to}, color: ##}或者用一個方法來返回如上格式的數組。
如果你想要着重渲染某一塊區域的或者某一條坐標線,可以使用from a to a
markings: [ { xaxis: { from: 0, to: 2 }, yaxis: { from: 0, to: 0.5 }, color: "#bb0000" }, ... ]
1 markings: function (axes) { 2 var markings = []; 3 for (var x = Math.floor(axes.xaxis.min); x < axes.xaxis.max; x += 2) 4 markings.push({ xaxis: { from: x, to: x + 1 } }); 5 return markings; 6 }
borderWidth & borderColor: 用來設置網格邊框的顏色和寬度。
minBorderMargin: 設置默認最小的網格的外邊距。
clickable & hoverable: 設置該屬性為true, plot會監聽鼠標在plot區域發生的事件並執行"plotclick"和“plothover”事件。該兩個事件的參數為function(position, dataItem)。如下是plotclick和plothover事件的用例:
1 $.plot($("#placeholder"), [ d ], { grid: { clickable: true } }); 2 3 $("#placeholder").bind("plotclick", function (event, pos, item) { 4 alert("You clicked at " + pos.x + ", " + pos.y); 5 // axis coordinates for other axes, if present, are in pos.x2, pos.x3, ... 6 // if you need global screen coordinates, they are pos.pageX, pos.pageY 7 8 if (item) {10 alert("You clicked a point!"); 11 } 12 });
當我們點擊plot區域的point時,item對象不為空,其內部屬性為:
item: { datapoint: the point, e.g. [0, 2] dataIndex: the index of the point in the data array series: the series object seriesIndex: the index of the series pageX, pageY: the global screen coordinates of the point }
pageX & PageY: 為該點在整個屏幕中的坐標值。
autoHighlight: boolean.如果設置為true,則點會自動被highlight。
mouseActiveRadius: 設置鼠標觸及該點多遠的距離仍然可以觸發事件,在兩個點相隔很近的時候,plot默認傳入最近的那個點的數據。對於柱狀圖,兩個柱子相隔很近的時候鼠標觸擊默認自動選擇最高的柱子。
keep updating!