關於dygraphs JavaScript Visualization Library的學習筆記
主要內容
1. 筆者留言
2. 什麼是dygraphs?
3. Dygraphs原理的簡單說明
4. Dygraphs的使用
5. IE兼容性、常見問題和建議
6. 自己寫的一個例子mydemo(主要是爲了說明Options的使用)
筆者留言
如果讀者的英文很好,可以直接無視這個筆記的大部分內容(除了注意點,IE兼容性和常見問題和建議)。
這個筆記,只是描述怎麼使用dygraphs。對其底層的原理,由於個人技術水平有限,沒有做太多的敘述。
文中的加紅部分的內容都是注意點。
如果發現文中有什麼地方有誤,請及時提出(回覆)。
本文原創,轉載請註明URL。
感想:
1. 開源的框架,源碼可以適當地修改,以符合我們的需求。
2. 多看看JS基礎知識
3. 多用度娘,Google。要注意分辨,多問人
4. 多做筆記
一、什麼是dygraphs?
Dygraphs是一個開源的JS庫;用於生成可與用戶交互的、可縮放的時間圖表。主要用於顯示密集的數據集合,用戶能夠很好的瀏覽和查看數據。
下面是相關的URL:
dygraphs JavaScript charting library
Copyright (c) 2006-, Dan Vanderkam.(感謝這個人)
Documentation(使用指南,demo位置等等): http://dygraphs.com/
Support: http://groups.google.com/group/dygraphs-users
Source(源碼發佈狀態): http://github.com/danvk/dygraphs
Issues: http://code.google.com/p/dygraphs/
源文件下載地址:https://github.com/danvk/dygraphs/downloads/
兩種格式:對應不同的操作系統
Zip (window xp)
tar.gz (linux )
我用的是window xp ,下了zip的
注意點:dygraph-combined.js — This is not the file you're looking for. Please use http://dygraphs.com/dygraph-combined.js instead <1KB
下載的zip中的dygraph-combined.js文件相當於是空的,要用下載這個地址的JS替換:
http://dygraphs.com/dygraph-combined.js
另下載的文件是js壓縮格式的 (compressed)
二、Dygraphs原理的簡單說明
JavaScript and the HTML canvas tag: js + <canvas>實現(在一個畫布上畫東東)
1.利用JS動態生成一個<canvas>添加到JS動態生成的DIV元素標籤(graphDiv包含了解1,2的所有內容)中,然後在<canvas></canvas>顯示數據(圖表);
(<canvas></canvas>會用DIV包含加入graphDiv)
2. 利用JS動態生成一個多個DIV元素標籤,分別包含X,Y軸,圖表標題的內容。加到第1步中DIV元素(graphDiv)中;
3. 在html, jsp等頁面中準備一個DIV元素標籤,來包含graphDiv。
當然還有其他的一些事件處理機制等等。
Ctrl + F graphDiv 可以在dygraph-combined.js找到相應的代碼
三、Dygraphs的使用
3.1、學習的兩種方式
進入dygraphs的首頁:http://dygraphs.com/
1. 可以把首頁的內容全部看完(在首頁的左邊的導航)
2.直接看例子(在首頁的左邊的導航)
3.2、第一個例子
結果圖:
圖1
可以在首頁的圖表中操作:在圖表中:
雙擊:還原;
按住左鍵,拖動選擇的圖表內容會放大;
在圖表上移動,高亮點 並 右上角會顯示相應時間點的數據。
在html,jsp 頁面中導入dygraph-combined.js和實例化一個
Dygraph
對象。
HTML
:
----------------------------------------------------------------------------------------------------------------
<html>
<head>
<script type="text/javascript" src="dygraph-combined.js"></script><!—
用這一個
js
就
OK
,封裝了這個框架所有基本的
JS
,不包括後面的
excanvas.js interaction.js-->
</head>
<body>
<div id="graphdiv2" style="width:500px; height:300px;"></div>
<script type="text/javascript">
g2 = new Dygraph(
document.getElementById("graphdiv2"),//
圖表顯示的位置
"temperatures.csv", //
數據的所在位置
{} // options
可選配置參數
);
</script>
</body>
</html>
---------------------------------------------------------------------------------------------------
3.2.1代碼說明
這是一個最簡單,最基本的例子。這裏主要講Dygraph對象的實例化:
構造函數有三個參數:
第一參數:圖表要顯示的位置(好像都是DIV元素)
第二參數:要顯示的數據
第三參數:可選配置參數
這裏最需要說明的是第二和第三個參數。
3.2.1.1第二參數:要顯示的數據
數據有5種表現形式:
3.2.1.1.1 CSV data
CSV data又有三種表現形式:本質一樣
(1) csv文件:這個有專門的軟件可以生成,沒有用過,不過我無意發現SQL Server數據庫查詢的結果可以保存成CSV文件。也可以直接TXT保存成CSV文件(應該可以,格式OK就行)。
(2) TXT文件 記事本文件(這個很容易得到,從數據庫中讀到數據,再用IO流寫到TXT)
(3)字符串
共同點:內容都必須符合一定的CSV格式
每條數據只佔一行,第一行一般是用來確定每一列的含義,每行中每個數據值用逗號分隔,如下:
Date,High,Low
20070101,62,39
20070102,62,44
20070103,62,42
20070104,57,45
從上面的數據可以看出:
第一列表示時間,第二列和第三列分別是High,Low在相應時間的數值。
在圖表顯示如上圖1所示。如果沒有第一行(Date,High,Low),就要用可選參數labels來指定每列數據的含義。如:
new Dygraph(el,
"2009/07/12,100,200\n" +
"2009/07/19,150,201\n",
{ labels: [ "Date", "Series1", "Series2" ] });
而"Date", "Series1", "Series2"分別對應圖表的X軸,Y1軸,Y2軸。(Y軸數據一般是number,其他沒有什麼要求)。
而X軸一般用來表示時間。它有兩種類型:
(1)日期格式字符串,支持以下幾種:
l 2009/07/12
l 2009/07/12 12
l 2009/07/12 12:34
l 2009/07/12 12:34:56
上面的數據格式字符串,會被自動解析成相應的時間
(2)數值格式(number)則是一個長整型(long),單位爲ms 。不能直接解析成一個時間對象,要作相應的配置。如:
new Dygraph(el,
"Date,Series1,Series2\n" +
"1247382000,100,200\n" +
"1247986800,150,201\n",
{//將long型轉換成Date
xValueFormatter: Dygraph.dateString_,
xValueParser: function(x) { return 1000*parseInt(x); },
xTicker: Dygraph.dateTicker
});
3.2.1.1.2 URL
通過一個URL訪問遠程的數據。
3.2.1.1.3 array (native format)
一個js中的Array對象;如:
[
[ new Date("2009/07/12"), 100, 200 ],
[ new Date("2009/07/19"), 150, 220 ]
]
這種數據格式,可以看到沒有指定(如:“Date,High,Low”)每列的含義。所以Array數據格式需要可選參數labels來指定每列的含義。例如:
new Dygraph(document.getElementById("graphdiv2"),
[
[1,10,100],
[2,20,80],
[3,50,60],
[4,70,80]
],
{
labels: [ "x", "A", "B" ]
});
3.2.1.1.4 function
Functions can return strings, arrays, data tables, URLs, or any other data type.
一個函數:返回字符串,Array對象,DataTable ,URL 和其他符合CSV 數據格式的數據類型。
3.2.1.1.5 DataTable
Google Visualization Library DataTable object: 谷歌可視化庫的數據表對象
3.2.1.2第三個參數:可選配置參數
第三個參數:框架中已經有相應的默認值,不過一般爲了達到自己的需求,都會配置一些參數。由於參數太多,這裏不做翻譯了。用的時候,可以結合相應的例子和Options reference來學習。文章最後是我寫的一個例子Mydemo(裏面對我用到的可選配置參數的作了一些註釋)。
3.3、Dygraph常用方法
g: 表示Dygraph對象實例
1. g.updateOptions({可選配置參數})
生成g對象後,用來更新可選配置參數,來改變圖表的某些狀態。下面是幾個函數,幫助理解:
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/**
* 右擊,縮小圖表
*
*/
function zoomGraph() {
var minDate = g.xAxisRange()[0]*(1.0000001); //x軸的最大和最小值(顯示出來的部分):long型
var maxDate = g.xAxisRange()[1]*(0.9999999);
g.updateOptions({ //更新可選配置參數
dateWindow: [minDate, maxDate]
});
}
/**
* 鼠標的滾輪的縮小圖表
*
*/
function zoomOutGraph() {
var minDate = g.xAxisRange()[0]*(0.9999999);
var maxDate = g.xAxisRange()[1]*(1.0000001);
g.updateOptions({
dateWindow: [minDate, maxDate]
});
}
/**
* 鼠標的滾輪的放大圖表
*/
function zoomInGraph() {
var minDate = g.xAxisRange()[0]*(1.0000001);
var maxDate = g.xAxisRange()[1]*(0.9999999);
// var minValue = g.yAxisRange()[0]*(1.01);//y軸的最大和最小值(顯示部分的)
//var maxValue = g.yAxisRange()[1]*(1.01);
g.updateOptions({
dateWindow: [minDate, maxDate]
// valueRange: [minValue, maxValue]
})
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2. g.setSelection(row)
定位圖表上的一點:參數row:將要選擇點的數據在CSV文件(如果第一行是:Date,series1,series2,則不包括這一行)的第幾行,從0開始。
(也就是圖表數據中第幾行(最小行爲0))
如下所示:
Date,High,Low (labels)
20070101,62,39 (row=0)
20070102,62,44 (row=1)
20070103,62,42 (row=2)
20070104,57,45 (row=3)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/**
*:通過地圖定位圖表上的一點
* @param time
* @param row
*/
function update(time,row){
var minDate = dygraphTime-300000;// x軸是long類型,這裏保持該點的左右各5分鐘
var maxDate = dygraphTime+300000;// 這個就是X軸的時間的long類型
g.updateOptions( {
dateWindow: [minDate, maxDate]// 這裏只能用鍵值對,不用函數。
});
var annotations = []; //清除所有點的註釋
g.setAnnotations(annotations);
g.setSelection(row);
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
四、IE的兼容性、常見問題和建議
對於IE兼容性問題:
最簡單的辦法:把http://dygraphs.com/tests/ 中隨便一個例子的<body>前面的內容複製就行。
一般要加:
<!DOCTYPE html> <!—IE本身不支持HTML5<canvas>; 這個是爲了在IE9中用微軟自己實現的canvas -->
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7; IE=EmulateIE9"> <!—兼容IE6-IE8 -->
<!--[if IE]><script src="path/to/excanvas.js"></script><![endif]--> <!--微軟自己實現的canvas -->
</head>
注意點:即使加了上面的內容;IE8可能會不支持HTML5<canvas>。(原因: <!DOCTYPE html>會破壞excanvas)
3. 在實例Dygraph對象的第三個參數(options)中
最後一個 name : value不要加” , ”。因爲IE不支持,會報錯(其他瀏覽器OK)。
如:
new Dygraph(el, data, {
rollPeriod: 5,
showRoller: true, // 最後一個配置,不要加逗號
})
4. 如果圖表不顯示,可以查看JS錯誤控制檯,dygraph本身封裝了日誌記錄功能:如error warning等
5. CSV文件必須是可讀的,否則XMLHttpRequest會取不到CSV文件。
6. CSV文件內容的格式正確。當用到errorBars時的CSV內容格式要注意。
7. 不要把要顯示圖表的DIV放到一個<center>標籤中,也不用CSS的樣式:text-align:center來使圖表居中。而是要用<table align=”center”><table>居中。
8.
dateWindow
屬性是一個
Array
對象,它的元素是
long
類型的,單位是
ms
。
dateWindow
不要直接使用符合
Date
對象的字符串或
Date
對象賦值,要做相應的處理得到日期的
ms
值:
Date.pase(string
str)
可以搞定)如:
g1 = new Dygraph(
document.getElementById("div_g1"),
data, {
dateWindow: [ Date.parse("2009/09/29 12:00:00"),
Date.parse("2009/10/10 12:00:00") ],
labels: [ 'Date', 'Y1', 'Y2' ]
}
);
五、
Mydemo
使用:把下面的代碼複製到一個HTML頁面中,然後放到下載的ZIP解壓後的danvk-dygraphs-681a215\tests文件夾,就可以使用了。
這個例子的特點是:
1. 交互:與百度地圖的操作相似
2. 在上面移動實時顯示數據註釋
測試:在IE firefox中測試OK
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7; IE=EmulateIE9">
<title>mydemo</title>
<!--[if IE]>
<script type="text/javascript" src="../excanvas.js"></script>
<![endif]-->
<!--
For production (minified) code, use:
壓縮格式的
dygraphs
的
JS
庫
<script type="text/javascript" src="dygraph-combined.js"></script>
-->
<script type="text/javascript" src="../dygraph-dev.js"></script><!--
要注意加載
JS
的順序,
excanvas.js
要在
dygraph-dev.js
的前面
-->
<script type="text/javascript" src="interaction.js"></script> <!--
用戶與圖表交互方式:如放大,縮小圖表的方式
-->
</head>
<body>
<h2>mydemo</h2>
<div id="my_chart" style="height:400px; border:1px solid black;"></div>
<script type="text/javascript">
/**
*
判斷系列名是
series1
還是
series2
,用不同的單位
* @param name
* @returns {String}
*/
function checkSerialName(name)
{
if(name=='series2')
{
return ' R/M';
}
else
{
return ' km/h';
}
}
var data = [];//
這裏定義了一個
Array
對象,這裏只顯示
3
個數據
data.push([1351571661000,0.0,678
]);
data.push([1351571672500,3.8,697
]);
data.push([1351571722500,31.0,1224
]);
var g = new Dygraph(
document.getElementById("my_chart"),//
圖表顯示位置
data, //'dygraphs/dygraphs.txt',
{
rollPeriod: 5,//
放大的倍數,不知道放大什麼,線看起來更圓滑
showRoller: true,//
顯示原點旁邊的小文本框
:rollPeriod
的值
//legend:'always',//
總是顯示右上角的數據
title:'title',//
標題
titleHeight:50,//
標題高度
avoidMinZero: true,//y
軸的最小值不爲
0
,相當於
y=0
那條線上升了。
axisLabelWidth:100,//X Y
軸的標題的寬度
width : 1500,//
圖表的寬度
height: 350,//
圖表的寬度和高度
xValueFormatter: Dygraph.dateString_,//
對
x
軸的
long
類型數據進行格式化成日期
xValueParser: function(x) { return parseInt(x); },
xTicker: Dygraph.dateTicker,
axisTickSize: 10,//
與時間軸的時間高度有關
//pixelsPerLabel:50,//
指定每個
x y
軸的
label
的顯示大小
axisLabelColor:'green',//
座標軸的刻度值顏色
highlightCircleSize: 6,//
高亮點顯示的大小
axisLineWidth:1,//
太小會看不到
Y
軸,默認爲
0.3
,以爲沒有畫出來
labels: [ 'Date', 'series1','series2'],//
這裏確定每列數據的含義
'series1': {//
用兩個
y
軸,這裏是指定用哪一個
y
軸
axis: {}
},
axes: {
y: {
valueRange: [500, 2600]//Y
軸的值範圍
},
y2: {
//set axis-related properties here
設置與
Y1
軸上每段值的相應的值(
labelsKMB
)
axisLabelFormatter: function(y2){//
對
Y
軸的刻度取整
return y2.toFixed(0);},
valueRange: [0, 100],
labelsKMB: true //
設置與
Y1
軸上每段值的相應的值(
labelsKMB
)
},
x: { //
顯示時分秒,不用也行
,
如果顯示
MS
,有個
demo
中,有
d.getMilliSeconds();
axisLabelFormatter: function(d, gran) {
return Dygraph.zeropad(d.getHours()) + ":"
+ Dygraph.zeropad(d.getMinutes()) + ":"
+ Dygraph.zeropad(d.getSeconds());
}
}
},
ylabel: 'series2',//y1
軸的標題
y2label: 'series1', //y2
軸的標題
//rightGap:0,//
這裏把
y
軸的名稱,頂沒了。
yLabelWidth:30, //Y
軸標題的寬度,可以作用所有
Y
軸
yAxisLabelWidth: 60, //
這個是
Y
軸刻度的寬度。
interactionModel : { //
用戶與圖表的交互方式,第一個例子中的方式是默認方式,
//
而現在配置這種是跟百度地圖等的操作方式相似的。
'mousedown' : downV3, //
注意這些事件的大小寫都不能寫錯。格式:
'
事件名稱
'
:事件發生時調用的函數
'mousemove' : moveV3, //
這些函數在
interaction.js
中
'mouseup' : upV3,
'click' : clickV3,
'mousewheel' : scrollV3, //IE
'DOMMouseScroll' : scrollV3,//
這個是
FireFox
的鼠標滑輪事件名稱,上面的是
IE
的
,
兩個都要
'dblclick' : dblClickV3
},
highlightCallback: function(e, x, pts, row){ //
除了高亮回調,
//
還有
drawCallback clickCallback dblclickCallback
用到時,可以去看
//
,形式是一樣的
addAnnotations(e, x, pts, row);//
加註釋
selectMapPoint(pts[0]);//
聚焦地圖的相應點
}
}//end of dygraphs options
);//end of dygraphs
/**
*
爲圖表中的線添加註釋
* @param e
鼠標移動事件
* @param x
高亮點對應的
x
的值(這個不確定)
* @param pts
高亮的點,有幾條線,就有幾個點
* @param row
該點數據在
CSV
文件(如果第一行是
:Date,series1,series2,
則不包括這一行)的第幾行,從
0
開始(也就是圖表數據中第幾行(最小行爲
0
))
*/
function addAnnotations(e, x, pts, row) {
annotations = [];
annotations.push( {
series: 'series2',//
在哪條線上加註釋
x: x,
width: 60,//
註釋的寬
height: 20,//
註釋的高
tickHeight: 5,//
線與註釋之間的距離,大的話,可以看到他們之間有條線連接
text:Math.round(pts[1].yval)+checkSerialName(pts[1].name),//
相當於一個
DIV
的
title
(源碼如此),鼠標在上,顯示這個
shortText: Math.round(pts[1].yval)+checkSerialName(pts[1].name)//
這個小文本直接顯示在註釋框內
} );
annotations.push( {
series: 'series1',
x: x,
width: 60,
height: 20,
tickHeight: 5,//
註釋框和線之前的線長
text:Math.round(pts[0].yval)+checkSerialName(pts[0].name),//
註釋的
title
shortText: Math.round(pts[0].yval)+checkSerialName(pts[0].name)
} );
g.setAnnotations(annotations); //
設置註釋
}
</script>
</body>
</html>
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------