1. 笔者留言
2. 什么是dygraphs?
3. Dygraphs原理的简单说明
4. Dygraphs的使用
5. IE兼容性、常见问题和建议
6. 自己写的一个例子mydemo(主要是为了说明Options的使用)
如果读者的英文很好,可以直接无视这个笔记的大部分内容(除了注意点,IE兼容性和常见问题和建议)。
这个笔记,只是描述怎么使用dygraphs。对其底层的原理,由于个人技术水平有限,没有做太多的叙述。
文中的加红部分的内容都是注意点。
如果发现文中有什么地方有误,请及时提出(回复)。
本文原创,转载请注明URL。
感想:
1. 开源的框架,源码可以适当地修改,以符合我们的需求。
2. 多看看JS基础知识
3. 多用度娘,Google。要注意分辨,多问人
4. 多做笔记
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)
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的首页:http://dygraphs.com/
1. 可以把首页的内容全部看完(在首页的左边的导航)
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>
---------------------------------------------------------------------------------------------------
这是一个最简单,最基本的例子。这里主要讲Dygraph对象的实例化:
构造函数有三个参数:
第一参数:图表要显示的位置(好像都是DIV元素)
第二参数:要显示的数据
第三参数:可选配置参数
这里最需要说明的是第二和第三个参数。
数据有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
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: 谷歌可视化库的数据表对象
第三个参数:框架中已经有相应的默认值,不过一般为了达到自己的需求,都会配置一些参数。由于参数太多,这里不做翻译了。用的时候,可以结合相应的例子和Options reference来学习。文章最后是我写的一个例子Mydemo(里面对我用到的可选配置参数的作了一些注释)。
g: 表示Dygraph对象实例
生成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]
})
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
定位图表上的一点:参数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兼容性问题:
最简单的办法:把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>
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------