九、jqPlot 折线图

Abstract

在前一章中,您观察到了 jqPlot 的最基本用法,其中一系列数据用来绘制一条线,不需要任何附加选项。您已经看到,为了创建最基本的图表类型,即折线图,您不需要包含插件。

在前一章中,您观察到了 jqPlot 的最基本用法,其中一系列数据用来绘制一条线,不需要任何附加选项。您已经看到,为了创建最基本的图表类型,即折线图,您不需要包含插件。

在本章中,您将通过探索各种插件及其功能,开始更详细地研究 jqPlot 库提供的可能性。首先,因为折线图是在笛卡尔轴上表示的,所以将向您介绍使用成对的值(x,y)作为输入数据。然后,您将继续学习轴以及如何使用适当的插件创建它们。您还将详细分析如何将连接到轴的各种元素实现为记号、轴标签和网格。对数标度的讨论如下。

接下来,您将学习如何通过同时处理多个系列的数据来实现多系列折线图。您将发现如何通过设置线条和标记来修改图案、形状甚至颜色。此外,您将看到如何通过调整浏览器绘制图表的速度来创建动画。

此外,您将研究 jqPlot 库允许您操作不同格式的日期和时间值的方式。您还将看到如何使用 HTML 格式定制一些元素,以及突出显示数据点。在本章的最后一部分,你将处理更复杂的情况,比如生成趋势线和使用波段图。

使用(x,y)对作为输入数据

到目前为止,为了简单起见,输入数据是以一个 y 值数组的形式传入的(见清单 9-1)。如果 jqPlot 只找到 y 值,则 x 值按照它们在数组中的顺序被指定为 1、2、3 等等。

清单 9-1。ch9_01.html

$(document).ready(function(){

var plot1 = $.jqplot ('myChart', [[100,110,140,130,80,75,120,130,100]]);

});

在图 9-1 中,你可以沿着 x 轴看到一系列整数,它们是作为数据传递的数组的索引。

A978-1-4302-6290-9_9_Fig1_HTML.jpg

图 9-1。

The x axis reports the indexes of the values inserted

当您使用线性图时,最好使用具有成对数值(x,y)的数组,因为这可以避免许多复杂情况,例如需要以特定顺序输入数据,而这并不总是可能或正确的。实际上,使用成对的值,数据不应该按照 x 值递增的顺序排列;jqPlot 会帮你做到。此外,x 的值不需要等距,而是可以遵循任何分布。在清单 9-2 中,插入了成对的值(x,y ),其中 x 值既没有排序也没有均匀分布。

清单 9-2。ch9_02.html

$(document).ready(function(){

var data = [[[10,100], [80,130], [65,75], [40,130],

[60,80], [30,140], [70,120], [20,110], [95,100]]];

$.jqplot ('myChart', data);

});

在图 9-2 中,你可以看到 jqPlot 是如何对图表中的所有点进行排序的,不管它们输入的顺序如何,也不管它们是否沿 x 轴均匀分布。

A978-1-4302-6290-9_9_Fig2_HTML.jpg

图 9-2。

A simple line chart with nonuniformly distributed points on the x axis

开发折线图的第一步:轴

在详细研究折线图的更复杂的方面之前,让我们先来看看这种图表的基础:轴。如果您想开发一个实现完美数据可视化的图表,对坐标轴的正确管理是至关重要的。为此,您需要很好地理解 jqPlot 库通过使用options对象中的特定属性提供的动作模式。

添加标题和轴标签

开发图表时,第一步是使用 CanvasAxisLabelRenderer 插件添加标题并管理轴标签。

但是,为了正常工作,这个插件需要另一个插件,一个提供编写功能的插件:CanvasTextRenderer。使用这个插件,您可以直接在画布元素上呈现标签文本。这允许您像对待任何其他图形元素一样对待文本,使您能够随心所欲地旋转文本。默认情况下,y 轴上的轴标签现在旋转了 90 度,如图 9-3 所示。

A978-1-4302-6290-9_9_Fig3_HTML.jpg

图 9-3。

Without including the CanvasAxisLabelRenderer plug-in , the y axis label is horizontal. When the plug-in is included, the y axis label is rotated vertically

要集成这一新功能,您需要将这两个插件添加到基本插件集中:

<script type="text/javascript" src="../src/plugins/jqplot.canvasTextRenderer.min.js">

</script>

<script type="text/javascript"

src="../src/plugins/jqplot.canvasAxisLabelRenderer.min.js"></script>

或者,如果您更喜欢使用内容交付网络(CDN)服务,您可以按如下方式操作:

<script type="text/javascript" src="http://cdn.jsdelivr.net/jqplot/1.0.8/plugins/jqplot.canvasTextRenderer.min.js></剧本>

<script type="text/javascript" src="http://cdn.jsdelivr.net/jqplot/1.0.8/plugins/jqplot.canvasAxisLabelRenderer.min.js></剧本>

创建了options变量之后,你必须在里面指定一些属性,如清单 9-3 所示。您已经看到了如何通过给title对象分配一个字符串来添加标题。然后,必须显式调用canvasAxisLabelRenderer对象来激活它的功能,通过在axesDefaults对象中这样做,它将对所有轴有效。要分配 x 轴和 y 轴标签中的文本,必须设置axes对象的xaxisyaxis子对象中的label属性。它的树形结构将允许你在每个单独的轴上进行不同的改变。

清单 9-3。ch9_03a.html

$(document).ready(function(){

var data = [[100, 110, 140, 130, 80, 75, 120, 130, 100]] ;

var options = {

title: 'My Line Chart',

axesDefaults: {

labelRenderer: $.jqplot.CanvasAxisLabelRenderer

},

axes: {

xaxis: {

label: "X Axis"

},

yaxis: {

label: "Y Axis"

}

}

};

$.jqplot ('myChart', data, options);

});

图 9-4 展示了清单代码生成的图表。

A978-1-4302-6290-9_9_Fig4_HTML.jpg

图 9-4。

A line chart with the y axis label vertically oriented

轴属性

与轴标签一样,有几个属性可以在axes对象中指定。例如,查看图表(见图 9.4),您可以看到直线从 x 值 1 开始,而 x 轴从值 0 开始,因此留下了一个空白。另一个空格出现在 x 范围的末端(9 到 10 之间)。如果您想要作用于这些距离(在轴的界限和数据集的端点之间),您必须使用pad属性。您可以应用填充来扩展数据边界上下的范围。数据范围乘以该因子,以确定最小和最大轴边界。值 0 将被解释为没有填充,并且pad将被设置为 1。因此,通过将pad属性添加到xaxis对象并将pad设置为 1(参见清单 9-4),您得到了图 9-5 中的图表。

清单 9-4。ch9_03b.html

xaxis: {

label: "X Axis",

pad: 1

},

A978-1-4302-6290-9_9_Fig5_HTML.jpg

图 9-5。

The same line chart as in Figure 9-4, with pad set to 1 on the x axis

现在,x 轴从值 1 开始,以 9 结束,代表数据系列的线也是如此。为了更好地理解填充的概念,你现在将设置pad属性为 2(见清单 9-5)。这意味着您想要将当前范围(10)扩大两倍。结果,你会得到一个 x 轴从-4 到 14 的图表,如图 9-6 所示。这是因为 jqPlot 倾向于以对称的方式保存数据,将其显示在中间。

清单 9-5。ch9_03c.html

xaxis: {

label: "X Axis",

pad: 2

},

A978-1-4302-6290-9_9_Fig6_HTML.jpg

图 9-6。

The same line chart, with pad set to 2 on the x axis

另一种控制数据显示范围的方法是使用minmax属性(见清单 9-6)。

清单 9-6。ch9_03d.html

xaxis: {

label: "X Axis",

min: 1,

max: 9

},

9-7 显示了具有新范围的 x 轴。

A978-1-4302-6290-9_9_Fig7_HTML.jpg

图 9-7。

The same line chart, with defined max and min on the x axis

其他有用的属性是那些控制细分(分割轴)及其底层数字术语的属性:ticks属性。由于它们的使用不仅限于axes对象下的简单选项——它们本身也是一个对象,并且需要一个渲染器插件才能工作——它们的处理值得用一个单独的章节来介绍。

坐标轴刻度

记号是显示图中记号或网格线值的组件。可以在options中的axes对象内指定图中刻度的行为,而且,作为一个对象本身,刻度有几个属性可以在tickOption属性内设置。例如,您可能需要为每个轴设置特定数量的网格线。这可以用不同的方法来完成。最简单的是直接指定numberTicks属性(见清单 9-7)。如果将其值设置为 5,您将在 x 轴上得到五个刻度:0、3、6、9 和 12(参见图 9-8 )。

清单 9-7。ch9_03e.html

xaxis: {

label: "X Axis",

numberTicks: 5

},

A978-1-4302-6290-9_9_Fig8_HTML.jpg

图 9-8。

A line chart with a prefixed number of ticks on the x axis

这也适用于 y 轴。在这种情况下,您需要在yaxis对象中设置相同的属性。从图中可以看出,x 轴的间隔是均匀的,因此刻度是等距的。另一种方法是直接定义你想要在图表上显示的刻度,如清单 9-8 所示。

清单 9-8。ch9_03f.html

xaxis: {

label: "X Axis",

ticks: [0,3,6,9,12]

},

这产生了相同的图表(见图 9-9 )。

A978-1-4302-6290-9_9_Fig9_HTML.jpg

图 9-9。

A line chart with directly defined ticks on the x axis

但是,当您希望刻度沿轴不均匀分布时,通常最好使用这种方法,如清单 9-9 所示。网格线也将遵循这种不均匀性,因为它将与每个刻度对应绘制(见图 9-10 )。

清单 9-9。ch9_03g.html

xaxis: {

label: "X Axis",

ticks: [1,2,3,7,9]

},

A978-1-4302-6290-9_9_Fig10_HTML.jpg

图 9-10。

A line chart with nonuniform, prefixed ticks on the x axis

刻度在图表中如此重要,以至于它们有一个专门针对它们的插件:CanvasAxisTickRenderer。

如果希望创建一个没有网格线的图表,同时保持刻度上的值,可以将showGridLine属性设置为'false'。但是,在此之前,您需要在 web 页面中包含插件:

<link rel="stylesheet" type="text/css" href="../src/jquery.jqplot.min.css" />

<script type="text/javascript"

src="../src/plugins/jqplot.canvasTextRenderer.min.js"></script>

<script type="text/javascript"

src="../src/plugins/jqplot.canvasAxisLabelRenderer.min.js"></script>

<script type="text/javascript"

src="../src/plugins/jqplot.canvasAxisTickRenderer.min.js"></script>

或者,如果您更喜欢使用 CDN 服务,您可以按如下方式操作:

<script type="text/javascript" src="http://cdn.jsdelivr.net/jqplot/1.0.8/pluginsT2】

/jqplot.canvasTextRenderer.min.js"></script>

<script type="text/javascript" src="http://cdn.jsdelivr.net/jqplot/1.0.8/pluginsT2】

/jqplot.canvasAxisLabelRenderer.min.js"></script>

<script type="text/javascript" src="http://cdn.jsdelivr.net/jqplot/1.0.8/pluginsT2】

/jqplot.canvasAxisTickRenderer.min.js"></script>

然后你必须在axesDefaults对象内进行设置,因为你想隐藏两个轴的网格线。记得调用刚刚包含在tickRenderer属性中的插件(见清单 9-10)。此外,您一定不要忘记删除在xaxis对象中定义的ticks属性。

清单 9-10。ch9_04a.html

axesDefaults: {

labelRenderer: $.jqplot.CanvasAxisLabelRenderer,

tickRenderer: $.jqplot.AxisTickRenderer,

tickOptions: {

showGridline: false

}

},

axes: {

xaxis: {

label: "X Axis"  //remove the comma here

},

如图 9-11 所示,你得到一个没有网格的图表。

A978-1-4302-6290-9_9_Fig11_HTML.jpg

图 9-11。

A line chart without grid lines

有时,你只需要隐藏一个轴的网格线,例如 x 轴(见图 9-12 )。在这种情况下,您必须只在xaxis对象内部调用渲染器。在清单 9-11 中,你可以看到必须从axesDefaults中删除然后写入xaxis对象的代码行。

清单 9-11。ch9_04b.html

axesDefaults: {

labelRenderer: $.jqplot.CanvasAxisLabelRenderer

//delete all this lines

//tickRenderer: $.jqplot.AxisTickRenderer,

//tickOptions: {

//showGridline: false

//}

},

axes: {

xaxis: {

label: "X Axis",

tickRenderer: $.jqplot.AxisTickRenderer,

tickOptions: {

showGridline: false

}

},

...

A978-1-4302-6290-9_9_Fig12_HTML.jpg

图 9-12。

A line chart with only horizontal grid lines

您可能希望添加的另一个功能是允许您将数值的格式作为字符串来处理。最常见的情况是,当您想要在 y 轴上显示百分比值时,这可能是有用的。要做到这一点,你需要在数值后面加上字符'%',如清单 9-12 所示。

清单 9-12。ch9_04c.html

yaxis: {

label: "Y Axis",

tickRenderer: $.jqplot.AxisTickRenderer,

tickOptions: {

formatString:'%d%'

}

}

如图 9-13 所示,图表现在在 y 轴上报告百分比值。

A978-1-4302-6290-9_9_Fig13_HTML.jpg

图 9-13。

A line chart reporting percentages on the y axis

稍后,您将看到这种字符串格式被证明是一种非常强大的工具的其他情况(参见“处理日期值”一节)。

使用对数标度

根据要在图表中表示的数据趋势,有时有必要在一个或两个轴上使用对数刻度。jqPlot 支持对数标度,包括 web 页面中的 LogAxisRenderer 插件。

<script type="text/javascript"

src="../src/plugins/jqplot.logAxisRenderer.min.js"></script>

LOG SCALE

对数标度使用与数量级(通常为 10)相对应的间隔,而不是标准的线性标度。这允许您在轴上表示大范围的值(v)。A978-1-4302-6290-9_9_Fig1a_HTML.jpg A978-1-4302-6290-9_9_Fig2a_HTML.jpg

对数是指数的另一种写法,你可以用它来分隔指数(x)并把它放在一个轴上。A978-1-4302-6290-9_9_Fig3a_HTML.jpg A978-1-4302-6290-9_9_Fig4a_HTML.jpg

例如,对数标度上一个点的增加对应于该值的 10 倍增加。同样,增加 2 个点相当于该值增加 100 倍。等等。

在想要以对数刻度表示数据的轴上,只需添加带有插件引用的renderer属性。在这种情况下,您需要创建一个近似遵循指数趋势的数据数组。所以,你在清单 9-13 中使用了[x,y]对的数组。

清单 9-13。ch9_11.html

var data = [[0,1.2],[10,2.4],[20,5.6],[30,12],[40,23],

[50,60],[60,120],[70,270],[80,800]];

接下来,你把 y 轴放在对数刻度上,如清单 9-14 所示。

清单 9-14。ch9_11.html

$.jqplot ('myChart', [data],{

axes:{

xaxis:{},

yaxis:{ renderer: $.jqplot.LogAxisRenderer }

}

});

在图 9-14 中,您可以看到数据是如何在半对数标度(一个轴上的对数标度)中呈现出近似于直线的形状。

A978-1-4302-6290-9_9_Fig14_HTML.jpg

图 9-14。

A line chart on a semilog scale on the y axis

多系列折线图

既然已经很好地指定了表示折线图的坐标轴,现在是处理多系列折线图的时候了。通常,您需要在同一个图表中显示多个数据系列。事实上,图表的目的通常就是比较不同的数据序列。

jqPlot 库为我们提供了管理多系列图表所需的工具。通过对线条和标记的图案、形状和颜色进行操作,可以引入有助于表示不同数据系列的图形效果。

多系列数据

到目前为止,您只处理了一组数据。但是,有时您希望一次表示多个数据集。在第 1 章中,你看到了在 jqPlot 中,多个系列的处理方式与单个系列相同。每个系列必须首先通过将它赋给一个变量来单独定义,然后在一个数组中与其他系列组合。然后这个数组作为第二个参数传递给jqPlot()函数(见清单 9-15)。

清单 9-15。ch9_05a.html

$(document).ready(function(){

var data1 = [1, 2, 3, 2, 3, 4];

var data2 = [3, 4, 5, 6, 5, 7];

var data3 = [5, 6, 8, 8, 7, 9];

var data4 = [7, 8, 9, 9, 10, 11];

var options = {

title:'Multiple Data Arrays'

};

$.jqplot ('myChart', [data1, data2, data3, data4], options);

});

图 9-15 显示了清单 9-15 中的多序列图表。

A978-1-4302-6290-9_9_Fig15_HTML.jpg

图 9-15。

A multiseries line chart

系统自动为每个系列赋予不同的颜色。这个颜色序列在 jqPlot 中被定义为缺省值。以下是 jqPlot 将按顺序分配给系列的颜色:

seriesColors: [  "#4bb2c5", "#c5b47f", "#EAA228", "#579575",

"#839557", "#958c12", "#953579", "#4b5de4",

"#d8b83f", "#ff5800", "#0085cc"]

这些值代表'#rrggbb',其中 rr、gg 和 bb 是红色、绿色和蓝色的十六进制值。浏览器结合这些值来生成系列所需的所有颜色。

当有超过 11 个系列时,jqPlot 将从头开始再次启动该系列。如果您不希望这样,或者只是需要做些不同的事情,您可以在seriesColors属性中定义一个不同颜色序列的数组,如清单 9-16 中给出的序列。图 9-16 显示了一种灰色的变化,但是运行这个例子,自己看看有什么不同(颜色从蓝色到紫色)。

Note

要检查颜色代码,我建议访问网站 HTML 颜色代码( http://html-color-codes.info )。

清单 9-16。ch9_05b.html

var options = {

seriesColors: ["#105567","#805567","#bb5567","#ff5567"],

title:'Multiple Data Arrays'

};

A978-1-4302-6290-9_9_Fig16_HTML.jpg

图 9-16。

A multiseries line chart with a customized color set

你也可以属性一个特定的颜色,使用两个函数:rgba( r , g , b , a )rgb( r , g , b )。将这些函数直接插入到分配给seriesColors属性的数组的每个值中,如清单 9-17 所示。

清单 9-17。ch9_05c.html

seriesColors: ["rgba(16,85,103,0.2)", "rgba(128,85,103,0.6)",

"rgb(187,85,103)", "rgb(250,85,103)"],

鉴于您已经通过获得给定颜色所需的红光、绿光和蓝光的组合来指定颜色,使用rgba()函数,引入了一个新变量a。这个a(代表“alpha”)代表一种颜色的不透明度。如图 9-17 所示,定义低 alpha 值可以让你看到有色物体背后的东西。

A978-1-4302-6290-9_9_Fig17_HTML.jpg

图 9-17。

A multiseries line chart with different levels of transparency

平滑线图

除了选择是否表示点标记和连接它们的直线,通常你会决定你想要得到一个平滑的曲线进展,如图 9-18 所示。这可以简单地通过使用smooth属性并将其设置为'true'来完成(见清单 9-18)。

清单 9-18。ch9_06.html

$(document).ready(function(){

var data1 = [1, 2, 3, 2, 3, 4];

var data2 = [3, 4, 5, 6, 5, 7];

var data3 = [5, 6, 8, 8, 7, 9];

var data4 = [7, 8, 9, 9, 10, 11];

var options = {

title:'Multiple Data Arrays',

seriesDefaults: {

rendererOptions: {

smooth: true

}

}

};

$.jqplot ('myChart', [data1, data2, data3, data4], options);

});

A978-1-4302-6290-9_9_Fig18_HTML.jpg

图 9-18。

A multiseries line chart with smoothed lines

线条和标记样式

设计折线图时,您需要考虑的另一个关键方面是线条和标记的显示方式。您可以使用线条、标记序列或两者来表示图表。默认情况下,jqPlot 显示每个系列,每个点对应于[x,y]对的点标记和一条按顺序连接它们的线。

所有这些都可以使用 series 对象的两个关键属性来控制:linePattern 和 lineWidth 在添加markerOptions属性的同时,还可以作用于影响标记组件的另外两个属性:style 和 size。清单 9-19 是这些设置的一个例子。

清单 9-19。ch9_07a.html

$(document).ready(function(){

var data1 = [1, 2, 3, 2, 3, 4];

var data2 = [3, 4, 5, 6, 5, 7];

var data3 = [5, 6, 8, 9, 7, 9];

var data4 = [7, 8, 9, 11, 10, 11];

var options = {

title: 'Multiple Data Arrays',

series:[{

linePattern: 'dashed',

lineWidth:2,

markerOptions: { style: 'diamond' }

},

{

showLine:false,

markerOptions: { size: 7, style: 'x' }

},

{

markerOptions: { style: 'circle' }

},

{

lineWidth:5,

linePattern: 'dotted',

markerOptions: { style: 'filledSquare', size: 10 }

}]

}

$.jqplot ('myChart', [data1, data2, data3, data4], options);

});

9-19 展示了清单 9-19 中设置的结果。

A978-1-4302-6290-9_9_Fig19_HTML.jpg

图 9-19。

In a line chart it is possible to set different markers and patterns

图表上的线条可以用linePattern属性绘制为实线、虚线或点线。默认情况下,绘制的每条线都是实心的,所以如果您想要一条线有不同的样式,有必要在options中指定。你可以在清单 9-19 中看到,可以将linePattern属性设置为'dotted''dashed',以便分别获得虚线或虚线。在清单 9-20 中,你可以看到也可以获得一个定制的线型,将格式定义为一个数组([破折号长度,间隙长度等等])。当分配给linePattern属性的数组有偶数个元素时,线条看起来最好,这样线条以破折号开始,以空格结束。linePattern属性也可以创建一个定制的模式,使用破折号(-)和点(.)字符的简写字符串符号。清单 9-20 提供了一些例子。

清单 9-20。ch9_07b.html

var options = {

title: 'Multiple Data Arrays',

seriesDefaults: {

showMarker: false

},

series: [{ linePattern: 'dashed'},

{ linePattern: 'dotted'},

{ linePattern: [4, 3, 1, 3, 1, 3]},

{ linePattern: '-.'}]

};

9-20 显示了清单 9-20 中使用的定制线条模式的例子。

A978-1-4302-6290-9_9_Fig20_HTML.jpg

图 9-20。

A multiseries line chart with different patterns

动画图表

当您在浏览器中加载网页时,您会注意到图表几乎是即时绘制的。你可以放慢绘图速度,根据你的喜好进行调整;当绘制元素时,较慢的速度会给图表带来浮动效果(见清单 9-21)。

清单 9-21。ch9_23.html

var options = {

title: 'Multiple Data Arrays',

seriesDefaults: {

showMarker: false,

rendererOptions: {

smooth: true,

animation: { show: true  }

}

}

};

9-21 显示了绘制图表的顺序,给人一种动画的感觉。

A978-1-4302-6290-9_9_Fig21_HTML.jpg

图 9-21。

An animated multiseries line chart

多个 y 轴

jqPlot 支持与同一个 x 轴相关的多个 y 轴。当您希望在单个图表中显示分布在不同 y 刻度上但具有相同 x 值的不同系列时,这很有用。在这种情况下,明智的做法是用相应系列的颜色来设置 y 轴,以便您可以确定任何给定点的正确 y 值。作为输入数据,让我们创建三个数据数组,它们包含相同的 x 值,但 y 值分布在不同的范围内,如清单 9-22 所示。使用相同的 x 值不是强制性的,但这样做是明智的。

清单 9-22。ch9_12.html

var data1 = [[10, 200], [20, 230], [30, 214], [40, 212], [50, 225], [60, 234]];

var data2 = [[10, 455], [20, 470], [30, 465], [40, 432], [50, 455], [60, 464]];

var data3 = [[10, 40], [20, 60], [30, 54], [40, 52], [50, 65], [60, 54]];

为每个 y 轴指定正确的数值范围是非常重要的,以便能够容易地比较不同系列的数值(见清单 9-23)。在series对象中,您需要明确指定三个值,每个值将一个序列分配给不同的 y 轴。如果您想保留特定系列的默认设置,即沿默认 y 轴的表示,您仍必须在对应于该系列的位置分配一个空对象{}。事实上,在这个例子中,series数组的第一个元素只是一个空对象{}.

此外,您需要将axesDefaults对象的useSeriesColor属性设置为'true'。这样,jqPlot 会将系列的颜色分配给相应的 y 轴。因此,通过使用三种默认颜色,第一个系列将为浅蓝色,第二个系列为橙色,第三个系列为灰棕色。

清单 9-23。ch9_12.html

var options = {

series:[

{},

{yaxis: 'y2axis'},

{yaxis: 'y3axis'}

],

axesDefaults:{useSeriesColor: true},

axes:{

xaxis: {min: 0, max: 70},

yaxis: {min: 190, max: 240},

y2axis: {min: 430, max: 480},

y3axis: {min: 35, max: 80}

}

};

$.jqplot ('myChart', [data1, data2, data3], options);

9-22 显示了三个系列,每个系列都以其 y 轴值表示。这里的轴以不同的灰度阴影显示,但它们实际上采用了与相关系列相对应的颜色。

A978-1-4302-6290-9_9_Fig22_HTML.jpg

图 9-22。

A multiseries line chart with multiple y axes

JavaScript 数据

如前所述,最好在jqPlot函数之外单独定义数据数组。您已经看到了如何创建一个包含 y 值或[x,y]对数值的数组。然而,因为 jqPlot 属于 JavaScript 领域,所以有另一种方法经常被证明是非常有用的:通过 JavaScript 方法生成数据序列。

使用数学函数生成数据

jqPlot 库是基于 JavaScript 的,并且和所有编程语言一样,它允许您实现生成值序列以用作输入数据的函数。例如,清单 9-24 采用了三个最常用和最著名的数学函数(正弦、余弦、幂)并通过它们创建了一个数据数组。

清单 9-24。ch9_08a.html

$(document).ready(function(){

var options = {

title:'Math function Arrays'

};

varcosPoints = [];

for (vari=0; i< 2 * Math.PI; i += 0.1){

cosPoints.push([i, Math.cos(i)]);

}

varsinPoints = [];

for (vari=0; i< 2 * Math.PI; i += 0.1){

sinPoints.push([i, 2 * Math.sin(i-.8)]);

}

varpowPoints = [];

for (vari=0; i< 2 * Math.PI; i += 0.1) {

powPoints.push([i, 2.5 + Math.pow(i/4, 2)]);

}

$.jqplot ('myChart', [cosPoints, sinPoints, powPoints], options);

});

9-23 说明了列表中三个函数生成的点如何在折线图上形成三个数学函数的特征趋势。

A978-1-4302-6290-9_9_Fig23_HTML.jpg

图 9-23。

A line chart reporting three different series of data generated from mathematical functions

因为这是一个具有高密度点的函数,并且因为这里的目标是突出趋势,所以最好不要显示标记点(见图 9-24 )。最好在options,中启用平滑,如清单 9-25 所示。

清单 9-25。ch9_08b.html

var options = {

title: 'Math function Arrays',

seriesDefaults: {

rendererOptions: {

smooth: true

},

markerOptions: { show: false }

}

};

A978-1-4302-6290-9_9_Fig24_HTML.jpg

图 9-24。

The same line chart, but rendered more legibly

生成随机数据

您已经看到了如何使用数学函数生成输入数据。同样,有时需要生成随机数据。例如,假设您刚刚完成 jqPlot 图表的编写,并且想要尝试输入虚拟数据。为此,使用随机生成的数据是最好的。清单 9-26 中的函数产生随机数据,每个点都是根据前一个点的值产生的。在每一步中,新值由一个随机数决定,该随机数与前一个数相加或相减。这会产生一系列连续的数据,从作为参数传递给函数的值开始。

清单 9-26。ch9_09.html

function generateRandomData(npts, start, delta) {

var data = [];

if (delta == null) {

delta = start;

start = (Math.random() - 0.5) * 2 * delta;

}

for (j=0; j<npts; j++) {

data.push([j, start]);

start += (Math.random() - 0.5) * 2 * delta;

}

return data;

}

您使用了三个参数:npts是要生成的点数,start是初始值,delta是每步随机加减的最大值。该函数返回一个数组,该数组将作为输入数据传递给图表。您可以从外部定义它:

var data = generateRandomData(30, 100, 1);

$.jqplot('myChart', [data]);

或者,你可以直接传递:

$.jqplot ('myChart', [makeContinuousData(30, 100, 1)]);

结果你得到了一个类似图 9-25 的图表(每次都会不一样)。

A978-1-4302-6290-9_9_Fig25_HTML.jpg

图 9-25。

A line chart representing a random series of data

处理日期值

日期类型是一种常用的值,尤其是在其他图表(如条形图)中。这些专门化的值不是那么容易处理的,jqPlot 有一个针对它们的插件:DateAxisRenderer。这个插件扩展了 JavaScript 的本机日期处理功能,允许您以任何明确的形式表示日期值,而不仅仅是以毫秒为单位。

DateAxisRenderer 插件

日期可以用多种方式表示,其格式因国家和用途而异。日期由日、月和年指示器组成。这些可以不同地排序,并且具有一位、两位或四位数字;或者,您甚至可能希望只使用一个或两个指示器(例如,月、年)。此外,各种字符充当分隔符。让我们以 04/07/2012 为例:“4”代表第四个月(四月),“7”是该月的第七天,“2012”是年份。这样的日期可以用多种方式显示:'07/04/2012''07/04/12''04/07/12''7-Apr-12''7-Apr''Apr-12''7 April''2012'等等。

日期值的标准格式如下:

'YYYY-MM-DD HH:MM<PM or AM>'

这个字符串包含了所有必要的信息——可能有点多。事实上,您通常只需要日期信息的一部分:有时,您可能只需要报告日和月,或者,如果您引用时间,您可能只需要处理小时和分钟,等等。

一旦包含了 DateAxisRenderer 插件,jqPlot 几乎可以接受任何可识别的值。在值被内部解析后,它将被呈现在调用插件的轴上,以tickOptions.formatString中指定的格式表示。

9-1 显示了可接受的格式代码。

表 9-1。

Date and Time Formats Accepted by jqPlot

| 密码 | 结果 | 描述 | | --- | --- | --- | | 年 |   |   | | %Y | Two thousand and eight | 四位数年份 | | %y | 08 | 两位数的年份 | | 月份 |   |   | | %m | 09 | 两位数的月份 | | %#m | nine | 一位数或两位数的月份 | | %B | 九月 | 完整的月份名称 | | %b | 九月 | 缩写月份名 | | 天 |   |   | | %d | 05 | 两位数的月份日期 | | %#d | five | 一位数或两位数的月份中的某一天 | | %e | five | 一位数或两位数的月份中的某一天 | | %A | 在星期日 | 星期几的全名 | | %a | 太阳 | 星期几的缩写名称 | | %w | Zero | 一周中的第几天(0 =星期日,6 =星期六) | | %o | 泰国(Thailand) | 一个月中某一天之后的序数后缀字符串 | | 小时 |   |   | | %H | Twenty-three | 24 小时制的小时数(两位数) | | %#H | three | 24 小时整数格式的小时数(一位数或两位数) | | %I | Eleven | 12 小时制的小时数(两位数) | | %#I | three | 12 小时整数格式的小时数(一位数或两位数) | | %p | 下午 | 上午或下午 | | 分钟 |   |   | | %M | 09 | 分钟(两位数) | | %#M | nine | 分钟(一位数或两位数) | | 秒 |   |   | | %S | 02 | 秒(两位数) | | %#S | Two | 秒(一位数或两位数) | | %s | 1206567625723 | Unix 时间戳(1970 年 1 月 1 日 00:00:00 之后的秒数) | | 毫秒 |   |   | | %N | 008 | 毫秒(三位数) | | %#N | eight | 毫秒(一到三位数) | | 时区 |   |   | | %O | Three hundred and sixty | 当地时间和格林威治标准时间(GMT)之间的时差(分钟) | | %Z | 山地标准时间(MST) | 浏览器报告的时区名称 | | %G | –06:00 | GMT 之间的小时和分钟 | | 快捷指令 |   |   | | %F | 2008-03-26 | %Y-%m-%d | | %T | 05:06:30 | %H:%M:%S | | %X | 05:06:30 | %H:%M:%S | | %x | 03/26/08 | %m/%d/%y | | %D | 03/26/08 | %m/%d/%y | | %#c | 2008 年 3 月 26 日星期三下午 3:31 | %a %b %e %H:%M:%S %Y | | %v | 2008 年 9 月 3 日 | %e-%b-%Y | | %R | twenty nine to four p.m. | %H:%M | | %r | 下午 3 时 31 分 | %I:%M:%S %p | | 特性 |   |   | | %n | \n | 换行 | | %t | \t | 标签 | | %% | % | 百分比符号 |

为了更清楚地了解 jqPlot 如何处理日期值,让我们看一系列说明各种格式的例子。然而,不管是哪种格式,您都必须在 web 页面的<head>部分包含 DateAxisRenderer 插件。

<script type="text/javascript"

src="../src/plugins/jqplot.dateAxisRenderer.min.js"></script>

处理不同格式的日期值

第一个例子处理一段时间内的汇率,每天的点值。为此,输入数据数组内部应该有一系列[x,y]值,其中 x 是一个日期值。x 值的序列不符合时间顺序;jqPlot 将沿着 x 轴对这些点进行排序。在清单 9-27 中,你使用了一系列的 x 输入值,前五个值有不同的格式。

清单 9-27。ch9_13a.html

var line1 = [['14-Oct-2012', 1300.41], ['2012-10-15', 1310.50],

['2012/10/16', 1322.88], ['17 Oct 2012', 1312.41],

['10/18/2012', 1308.16], ['19-Oct-2012', 1310.71],

['20-Oct-2012', 1305.01],['21-Oct-2012', 1300.85],

['22-Oct-2012', 1290.67]];

接下来,您必须调用options中的xaxis对象内部的渲染器来激活它。您希望表示一个月中跟随汇率值趋势的日子,因此您将设置不包括年份的输出格式,年份保持不变。此外,在开始时,您希望以数字形式显示一个月中的某一天,然后用前三个字符书写月份,中间用空格隔开。简单地说,在清单 9-28 中,格式将是'%d %b',其中%d代表数字形式的日,%b,代表月份的前三个字符。y 值是美元,所以需要添加美元符号($)作为 y 轴刻度的前缀。为此,您还必须对 y 刻度使用formatString属性。

清单 9-28。ch9_13a.html

var options = {

title: 'Handling Date Values',

axes:{

xaxis:{

renderer: $.jqplot.DateAxisRenderer,

tickOptions:{

formatString:'%d %b'

}

},

yaxis:{

tickOptions:{

formatString:'$%d'

}

}

}

};

$.jqplot('myChart', [line1], options);

9-26 显示美元值,前缀$,在 y 轴上,日和月在 x 轴上。这只是您可以设置来表示刻度值的几种格式之一。

A978-1-4302-6290-9_9_Fig26_HTML.jpg

图 9-26。

A line chart with date values on the x axis

处理时间值

假设您想要绘制一个图表来表示参观博物馆的次数。可以在输入数据中明确显示时间(小时、分钟、秒)。这允许你以与前一个例子(见清单 9-27)相同的方式处理这些时间值,例如,通过创建一个包含某一天收集的数据的图表。这里也可以用前面讨论过的任何格式设置日期。您可以用各种方式表示时间:12 小时格式,带 am 或 pm 后缀,或者直接用 24 小时格式,包括或忽略秒和分钟。清单 9-29 展示了一个以 2 小时为间隔的时间值序列。

清单 9-29。ch9_13b.html

var line1 = [['2012-10-14 08:00AM', 30],['2012-10-14 10:00AM', 60],

['2012-10-14 00:00PM', 120], ['2012-10-14 02:00PM', 60],

['2012-10-14 04:00PM', 100], ['2012-10-14 06:00PM', 40]];

关于输出格式,您必须记住还要管理时间格式;因为您只对一天中的几个小时感兴趣,所以您将'%R'设置为'formatString'(见清单 9-30)。

清单 9-30。ch9_13b.html

var options = {

title: 'Museum Visitors',

axes:{

xaxis:{

label: 'time',

renderer:$.jqplot.DateAxisRenderer,

tickOptions:{

formatString: '%R'

}

},

yaxis:{

label: 'visitors'

}

}

};

$.jqplot('myChart', [line1], options);

浏览器将显示如图 9-27 所示的图表。

A978-1-4302-6290-9_9_Fig27_HTML.jpg

图 9-27。

A bar chart with time values on the x axis

突出

可以添加到图表中的一个引人注目的效果是突出显示(即,让您的绘图对鼠标悬停做出反应。例如,荧光笔插件会高亮鼠标附近的数据点,具有很好的动态效果。这可以通过显示带有数据点值的工具提示来增强。

光标荧光笔

下面的例子将帮助你熟悉高亮显示。该功能非常重要,当鼠标悬停在图表中的特定元素上时会激活一个事件。通常,这些是表示数据的元素,例如,在折线图中,用一个点(或者,更准确地说,用标记;您会发现这也适用于其他类型的图表:条形图中的条形、饼图中的切片等等。

默认情况下,触发的事件只是数据的一个突出显示,由显示其(x,y)值的工具提示表示。

要将这些功能添加到图表中,您必须包括一组插件:

<script type="text/javascript" src="../src/plugins/jqplot.highlighter.min.js">

</script>

<script type="text/javascript" src="../src/plugins/jqplot.cursor.min.js">

</script>

在清单 9-31 中,作为输入数据,你使用了一系列的[x,y]对,其中日期值在 x 轴上,数值在 y 轴上。

清单 9-31。ch9_14a.html

var line1 = [['14-Oct-12', 1300.41], ['15-Oct-12', 1310.50],['16-Oct-12', 1322.88],

['17-Oct-12', 1312.41],['18-Oct-12', 1308.16],['19-Oct-12', 1310.71],

['20-Oct-12', 1305.01],['21-Oct-12', 1300.85],['22-Oct-12', 1290.67]];

正如您已经看到的,为了处理日期值,您需要包括 DateAxisRenderer 插件。

<script type="text/javascript"

src="../src/plugins/jqplot.dateAxisRenderer.min.js"></script>

在清单 9-32 中,你可以看到options对象,包含两个新对象:highlightercursor

清单 9-32。ch9_14a.html

var options = {

title: 'Data Point Highlighting',

axes:{

xaxis:{

renderer: $.jqplot.DateAxisRenderer,

tickOptions:{

formatString: '%b&nbsp;%#d'

}

},

yaxis:{

tickOptions:{

formatString: '$%d'

}

}

},

highlighter:{

show: true,

sizeAdjust: 7.5

},

cursor:{

show: false

}

};

在图 9-28 中,当光标移动到图表上的数据点上时,会出现一个工具提示。默认情况下,此工具提示使用轴格式化程序报告 x 和 y 值,用逗号分隔,但这可以用不同的格式字符串自定义。

A978-1-4302-6290-9_9_Fig28_HTML.jpg

图 9-28。

Data point highlighting on a line chart

在清单 9-32 中,你会注意到光标已经被禁用,通过将它的show属性设置为'false'(默认情况下是启用的)。启用它,如清单 9-33 所示,你会看到鼠标光标在进入图形区域时发生变化,并在右下角显示一个可选的工具提示,报告鼠标位置。工具提示可以位于固定位置,也可以跟随鼠标移动。默认设置为'crosshair'的指针样式也可以自定义。

清单 9-33。ch9_14b.html

...

highlighter: {

show: true,

sizeAdjust : 7.5

}

cursor: {

show: true,

tooltipLocation:'ne'

}

});

9-29 显示了报告光标坐标的工具提示。请注意,光标由图表中间的黑色十字表示。

A978-1-4302-6290-9_9_Fig29_HTML.jpg

图 9-29。

A line chart showing the cursor coordinates

用 HTML 格式突出显示

您可以使用 HTML 标签作为格式来更改工具提示的内容。这使得定制的可能性几乎是无限的。事实上,你可以把工具提示想象成一个小小的网页,可以在其中添加任何类型的元素,比如一张图片或者一个锚链接(更多细节,参见第 1 章 0)。例如,您可以使用清单 9-34 所示的设置,将 HTML 格式字符串分配给formatString属性。

清单 9-34。ch9_14c.html

highlighter: {

show: true,

sizeAdjust: 7.5,

showMarker: false,

tooltipAxes: 'xy',

yvalues: 4,

formatString:'<table class="jqplot-highlighter"> \

<tr><td>date:</td><td>%s</td></tr> \

<tr><td>value:</td><td>%s</td></tr></table>'

},

因此,带有内容的工具提示将表现得像一个小的 HTML 页面,如图 9-30 所示。

A978-1-4302-6290-9_9_Fig30_HTML.jpg

图 9-30。

A line chart with an HTML tool tip

与图表交互:限制线条和缩放

一旦你有了一个包含图形和元素的折线图,下一步就是引入交互元素。例如,用户可能需要使用阈值来查看这些值之外的数据。用户可能还需要改变该阈值,以确定哪些数据在阈值之内,哪些数据在阈值之外。通常,会表示大量数据。在这种情况下,用户可能只需要分析一个细节。

jqPlot 库为限制线和缩放这两种情况提供了解决方案。让我们来看一些详细解决这些问题的例子。

在图表上画一条界限线

另一个非常有用的特性是 CanvasOverlay 插件。它能让你在图表上画水平线和垂直线,目的是指示一个极限、一个阈值、一个截止日期或划定一个特定的范围。这可以通过在网页中包含 CanvasOverlay 插件来实现:

<script type="text/javascript"

src="../src/plugins/jqplot.canvasOverlay.min.js"></script>

通过包含这个插件,您在options : canvasOverlay中有了一个新对象。在这个对象中,您将使用对象的属性定义一个对象数组。这些对象中的每一个都将由绘制在画布上的一条线来表示,jqPlot 在画布上创建您的图表。在canvasOverlay中已经定义了五种类型的对象:

  • horizontalLine
  • verticalLine
  • dashedHorizontalLine
  • dashedVerticalLine
  • Line (generic)

要查看如何在图表中插入这些限制线,让我们从一个简单的折线图开始,在该折线图中,您希望显示两条不同颜色的水平限制线:一条红线标记上限,一条蓝色虚线标记下限。

在清单 9-35 中,你定义了两个对象:一个是下限的horizontalLine,一个是上限的dashedHorizontalLine。一旦定义了这两条线,就必须指定它们的属性。它们的属性,比如 y 值、lineWidthcolor,其含义是显而易见的。lineCap属性指定放置在线条上的结束类型;可以是roundbuttsquare

清单 9-35。ch9_15.html

$(document).ready(function(){

var data = [100, 110, 140, 130, 80, 75, 120, 130, 100];

var options = {

canvasOverlay: {

show: true,

objects: [

{horizontalLine: {

y: 70,

lineWidth: 3,

color: 'rgb(255, 0, 0)',

shadow: true,

lineCap: 'butt'

}},

{dashedHorizontalLine: {

y: 145,

lineWidth: 4,

color: 'rgb(0, 0, 255)',

shadow: false,

dashPattern: [8, 16],

lineCap: 'round'

}}

]

}

};

$.jqplot('myChart', [data], options);

});

9-31 显示了在值 70 和 145 之间界定线图的两条极限线。

A978-1-4302-6290-9_9_Fig31_HTML.jpg

图 9-31。

A line chart with lower and upper limits

您已经看到了如何在两条界限线之间划定折线图,在更复杂的情况下(但不是在这种情况下,这种情况不太常见),可以方便地改变这些界限的值,从而能够随意移动它们,例如,通过单击一系列按钮。在下一个示例中,您将继续通过添加按钮来实现当前图表,这些按钮用于滑动图表表面上的限制线。

向图表添加按钮

使用前面的例子(见清单 9-35),你将看到如何在图表中添加按钮。按钮可以放在网页的任何部分,因为它们在画布之外。在这里,它们的功能是允许您随意移动限制线,只需单击它们即可。

为此,您需要四个按钮:两个用于向上移动限制线,两个用于向下移动限制线,标记如下:

  • 下限上限
  • 下限下降
  • 上限向上
  • 上限下降

你可以在网页的<body>部分的任何地方添加清单 9-36 中定义的四个按钮。

清单 9-36。ch9_16.html

<div>

<button onclick="lineup(myPlot, 'lowlimit')">Low Limit Up</button>

<button onclick="linedown(myPlot, 'lowlimit')">Low Limit Down</button>

</div>

<div>

<button onclick="lineup(myPlot, 'hilimit')">High Limit Up</button>

<button onclick="linedown(myPlot, 'hilimit')">High Limit Down</button>

</div>

这些行将生成如图 9-32 所示的四个按钮。

A978-1-4302-6290-9_9_Fig32_HTML.jpg

图 9-32。

The buttons added to the chart in order to move the limit lines

在第 2 章中,向您介绍了可以用作控件的 JQuery 用户界面库(jQuery UI)小部件。考虑到这种类型控件的潜力,建议使用库提供的按钮部件(关于如何使用这些部件的更多信息,参见第 1 章 5)。如果您希望使用 jQuery UI 小部件来替换这四个按钮,那么您需要包括以下插件:

<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css>

<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.min.jsT2】

但是,如果您希望引用本地安装的库(参见附录 A),则必须包含以下代码:

<link rel="stylesheet" href="../src/css/smoothness/jquery-ui-1.10.3.custom.min.css" />

<script src="../src/js/jquery-ui-1.10.3.custom.min.js"></script>

并且,在 HTML 页面的<body>部分,添加清单 9-37 中的代码。

清单 9-37。ch9_16.html

<script>

$(function() {

$('button')

.button()

.click(function( event ) {

event.preventDefault();

});

});

</script>

按钮现在以 jQuery UI 风格显示(或者,更准确地说,以“平滑度”为主题,这是其中之一),如图 9-33 所示。

A978-1-4302-6290-9_9_Fig33_HTML.jpg

图 9-33。

The same four buttons, but displayed using the jQuery UI

此时,这些按钮完全处于非活动状态。你需要开发两个 JavaScript 函数;当按钮被按下时,这些将被执行。第一个函数lineup()将增加作为参数传递的线的 y 值(上限或下限),然后强制绘制新的图表。第二个函数linedown()将减少 y 值。这两个函数必须在 jQuery 函数$(document).ready()的外部(见清单 9-38)。

清单 9-38。ch9_16.html

function lineup(plot, name) {

var co = plot.plugins.canvasOverlay;

var line = co.get(name);

line.options.y += 5;

co.draw(plot);

}

functionlinedown(plot, name) {

var co = plot.plugins.canvasOverlay;

var line = co.get(name);

line.options.y -= 5;

co.draw(plot);

}

下一步是将由$.jqplot()函数返回的对象赋给一个变量:

myPlot = $.jqplot('myChart', [data], options);

Note

注意不要写varmyPlot,否则当你按下按钮时,你将看不到图表的任何变化。

最后一步是命名canvasOverlay对象中的两条线,如清单 9-39 所示。

清单 9-39。ch9_16.html

objects: [

{horizontalLine: {

name: 'lowlimit',

y: 70,

lineWidth: 3,

color: 'rgb(255, 0, 0)',

shadow: true,

lineCap: 'butt'

}},

{dashedHorizontalLine: {

name: 'hilimit',

y: 145,

lineWidth: 4,

color: 'rgb(0, 0, 255)',

shadow: false,

dashPattern: [8, 16],

lineCap: 'round'

}}

]

最后,你得到一个包含四个按钮的图表,如图 9-34 所示。

A978-1-4302-6290-9_9_Fig34_HTML.jpg

图 9-34。

A line chart with a set of buttons that vary the lower and upper thresholds

有时,您需要在图表中添加垂直线,尤其是当您必须标记截止日期时。在这种情况下,我们将像以前一样工作,但有一些不同。例如,假设您想要在折线图中放置一条竖线来表示截止日期。在这种情况下,您使用清单 9-40 中的代码。

清单 9-40。ch9_17.html

$(document).ready(function(){

var data = [100, 110, 140, 130, 80, 75, 120, 130, 100];

var options = {

canvasOverlay: {

show: true,

objects: [

{verticalLine: {

name: 'lowlimit',

x: 5,

lineWidth: 3,

color: 'rgb(50, 200, 50)',

shadow: true,

lineCap: 'butt',

yOffset: 0

}}

]

}

};

myPlot = $.jqplot('myChart', [data], options);

});

这一次,您将只需要两个按钮。

<div>

<button onclick="lineright(myPlot, 'lowlimit')">Postpone Deadline</button>

<button onclick="lineleft(myPlot, 'lowlimit')">Anticipate Deadline</button>

</div>

现在,您必须开发两个 JavaScript 函数,它们将在按钮被按下时水平移动界限线。像前面看到的 JavaScript 函数一样,清单 9-41 中的两个函数必须放在 jQuery 函数$(document).ready()的外部。

清单 9-41。ch9_17.html

functionlineright(plot, name) {

var co = plot.plugins.canvasOverlay;

var line = co.get(name);

line.options.x += 1;

co.draw(plot);

}

functionlineleft(plot, name) {

var co = plot.plugins.canvasOverlay;

var line = co.get(name);

line.options.x -= 1;

co.draw(plot);

}

结果就是图 9-35 中的图表,中间有一条绿色竖线。通过点击这两个按钮,如果你想提前,线条会向左移动,如果你想推迟,线条会向右移动。

A978-1-4302-6290-9_9_Fig35_HTML.jpg

图 9-35。

A line chart with a green horizontal limit line

变焦

通常,当您处理大量数据时,图表上会出现一条由数千个点组成的线。正是在这种情况下,变焦功能是必不可少的。从宏观视图开始,您可以放大线的一部分以获得数据的微观视图。

光标插件还支持绘图缩放功能。通过在图上单击并拖动光标,可以放大和滚动图表的小部分。如果双击,可以全部重置,回到宏观视图。因此,您需要在您的 web 页面中包含光标插件,并且因为您在 x 轴上有日期值,所以还必须包含 DateAxisRenderer 插件:

<script type="text/javascript"

src="../src/plugins/jqplot.dateAxisRenderer.min.js"></script>

<script type="text/javascript" src="../src/plugins/jqplot.cursor.min.js"></script>

或者,如果您更喜欢使用 CDN 服务,您可以按如下方式操作:

<script type="text/javascript" src="http://cdn.jsdelivr.net/jqplot/1.0.8/pluginsT2】

/jqplot.dateAxisRenderer.min.js"></script>

<script type="text/javascript"

src="http://cdn.jsdelivr.net/jqplot/1.0.8/plugins/jqplot.cursor.min.jsT2】

清单 9-42 说明了大量输入数据的可用性。

清单 9-42。ch9_18.html

var data = [["6/22/2012 10:00:00", 110.32], ["6/8/2012 10:00:00", 115.84],

["5/26/2012 10:00:00", 121.23], ["5/11/2012 10:00:00", 122.12],

["4/27/2012 10:00:00", 120.69], ["4/13/2012 10:00:00",123.24],

["3/30/2012 10:00:00", 116.78], ["3/16/2012 10:00:00", 115.16],

["3/2/2012 10:00:00", 113.57], ["2/17/2012 10:00:00", 120.45],

["2/2/2012 10:00:00", 121.28], ["1/20/2012 10:00:00", 124.7],

["1/5/2012 10:00:00", 130.07], ["12/22/2011 10:00:00", 129.36],

["12/8/2011 10:00:00", 130.76], ["11/24/2011 10:00:00", 133.96],

["11/10/2011 10:00:00", 140.02] ,["10/27/2011 10:00:00", 138.36],

["10/13/2011 10:00:00", 140.54], ["9/29/2011 10:00:00", 140.91],

["9/15/2011 10:00:00", 140.15], ["9/2/2011 10:00:00", 138.25],

["8/25/2011 10:00:00", 137.29], ["8/11/2011 10:00:00", 139.15],

["7/28/2011 10:00:00", 144.86], ["7/14/2011 10:00:00", 145.32],

["6/30/2011 10:00:00", 148.12], ["6/16/2011 10:00:00", 146.43],

["6/2/2011 10:00:00", 147], ["5/19/2011 10:00:00", 144.62],

["5/5/2011 10:00:00", 143.2], ["4/21/2011 10:00:00", 144.06],

["4/7/2011 10:00:00", 137.45], ["3/24/2011 10:00:00", 138.08],

["3/10/2011 10:00:00", 137.92], ["2/25/2011 10:00:00", 131.18],

["2/11/2011 10:00:00", 129.64], ["1/28/2011 10:00:00", 133.9],

["1/14/2011 10:00:00", 134.25], ["12/31/2010 10:00:00", 137],

["12/17/2010 10:00:00", 136.69], ["12/3/2010 10:00:00", 144.87],

["11/19/2010 10:00:00", 146.7], ["11/5/2010 10:00:00", 143.97],

["10/22/2010 10:00:00", 139.6], ["10/8/2010 10:00:00", 133.39],

["9/24/2010 10:00:00", 130.27], ["9/10/2010 10:00:00", 132.75],

["8/27/2010 10:00:00", 130.25]];

启用缩放功能非常简单。只需在options中将zoom属性设置为'true',如清单 9-43 所示。

清单 9-43。ch9_18.html

var options = {

series: [{

neighborThreshold: -1

}],

axes:{

xaxis:{

renderer: $.jqplot.DateAxisRenderer,

min:'August 1, 2010 16:00:00',

tickInterval: '6 months',

tickOptions: {formatString: '%#m/%#d/%Y'}

}

},

cursor:{

show: true,

zoom: true,

showTooltip: false

}

};

myPlot = $.jqplot('myChart', [data], options);

或者,如果您愿意,您可以禁用重置缩放的双击。光标插件还通过在外部使用resetZoom()方法来扩展绘图对象(由$.jqplot()函数返回的值)。此外,可以从用户代码或另一个 HTML 元素(如按钮)调用此方法来重置绘图缩放。

您可以在 jQuery ready()函数中定义这个函数:

$('.button-reset').click(function() { myPlot.resetZoom() });

然后,在您想要的任何位置插入以下行,以便将按钮放在网页的<body>部分:

<button class="button-reset">Reset Zoom</button>

9-36 提供了代表不同时刻的折线图的一系列图片。第一张图片是从浏览器显示的折线图,没有任何缩放。第二张图片显示了用户选择的图表区域,目的是进行缩放。最后一张图片展示了这种缩放的结果。如果用户单击重置缩放按钮,浏览器将再次显示第一张图片。

A978-1-4302-6290-9_9_Fig36_HTML.jpg

图 9-36。

A detail of the line chart extracted by zooming

更改图表外观

多亏了它的几个插件,jqPlot 可以直接在画布上呈现图表组件,包括文本。到目前为止,很明显 jqPlot 库的亮点是可以通过改变 jqPlot 属性和添加的插件的默认值来改变任何图表元素的外观。但是,这不是实现这种改变的唯一方法。如果您想要修改 HTML 页面中元素的外观,您可以求助于 CSS 样式。即使对于 jqPlot 元素也是如此。

可以用 CSS 类引用几个(但不是全部)jqPlot 对象,以改变这些对象的样式,而不必在options中设置它们的属性。对象可以由 CSS 定制,使用 CSS 类,如.jqplot-*

自定义文本,使用 CSS

jqPlot 库提供了 CSS 类,使用这些类,您可以在不引用options对象的情况下更改一些属性。举例来说,您将使用其中一些类来更改图表中的文本。让我们从实现一个简单的多系列折线图开始,它只有一个标题和一个在options中定义的轴标签(见清单 9-44)。

清单 9-44。ch9_10a.html

$(document).ready(function(){

var data1 = [1, 2, 3, 2, 3, 4];

var data2 = [3, 4, 5, 6, 5, 7];

var data3 = [5, 6, 8, 9, 7, 9];

var data4 = [7, 8, 9, 11, 10, 11];

var options = {

title: 'Multiseries Line Chart,

axesDefaults: {

label: 'Axis Label'

}

};

$.jqplot('myChart',[data1, data2, data3, data4], options);

});

您在清单 9-45 中添加了<style>部分,它可以被提取为一个 CSS 文件。

清单 9-45。ch9_10a.html

<style>

.jqplot-title {

font-family: "Arial Black";

font-size: 24px;

color: lightblue;

}

.jqplot-xaxis-label {

font-size: 24px;

}

.jqplot-axis {

font-family: "Arial";

font-size: 16px;

}

.jqplot-xaxis {

color: green;

}

.jqplot-yaxis {

color: orange;

font-weight: bold;

}

</style>

9-37 展示了清单 9-45 中 CSS 样式设置前后的情况,让我们看到了所做的改动。

A978-1-4302-6290-9_9_Fig37_HTML.jpg

图 9-37。

Some CSS styles applied to the tick labels and title

更改背景颜色

继续上一个例子(见清单 9-45),你现在发现只要简单地添加一个属性到options(在清单 9-46 中突出显示),你就可以获得一个黑色背景。如图 9-38 所示。

清单 9-46。ch9_10b.html

var options = {

title: 'Multiple Data Arrays',

axesDefaults: {

label: 'Axis Label'

},

grid: {

background: '#000000'

}

};

A978-1-4302-6290-9_9_Fig38_HTML.jpg

图 9-38。

A line chart with a black background

使用 CSS 进一步定制

这一次,您不仅要更改网格的背景,还要更改图表周围的空间,使其更具吸引力。您可以通过将 CSS 样式直接应用于图表元素来实现这一点。

例如,与默认设置(灰色网格,白色背景)相反,假设您决定将图表放置在全黑背景上。在这种情况下,您需要创建一个容器,在myChart目标(另一个<div>元素)中包含一个<div>元素:

<div class="chart-container">

<div id="myChart" style="height:400px; width:500px;"></div>

</div>

该容器用于扩展将放置黑色背景的区域;我们通过用chart-container设置其类来引用容器。

此时,要记住的最重要的事情是,容器和目标这两个元素现在可以通过更改它们的 CSS 样式来适当地表征。这可以通过为.chart-container指定属性来实现,如清单 9-47 所示(至于目标的元素,已经使用.jqplot-*类设置好了)。在.chart-container类中,你将background属性设置为'black';容器的大小由widthheight属性确定。您还可以使用padding属性来更好地将目标放在容器的中心。填充清除元素内容周围的区域,扩展其背景色。这四个值分别是顶部、右侧、底部和左侧填充。

清单 9-47。ch9_20.html

<style type="text/css">

.chart-container {

background : #000000;

padding: 30px 0px 80px 30px;

width: 560px;

height: 330px;

}

...

</style>

容器和目标的 CSS 定制的组合结果如图 9-39 所示。

A978-1-4302-6290-9_9_Fig39_HTML.jpg

图 9-39。

A multiseries line chart with a black background

设置网格

默认情况下,图表的网格是灰色的。然而,在前面的例子中(见清单 9-47),你看到了如何通过设置optionsgrid对象的属性来改变网格。在本例中,您将继续修改相同的多系列折线图,但这一次,您将关注网格属性。

您可以更改网格颜色和厚度。例如,您可能想要一个黑色的网格,增加厚度,在这种情况下,您必须定义gridLineColorgridLineWidth属性。此外,有时,默认情况下,jqPlot 可能会用太粗的网格显示图表,这可能会妨碍而不是有助于可读性。在这种情况下,您需要减少分笔成交点的数量。这很容易做到,通过以特定的方式为options中的axes对象内的每个轴设置numberTicks属性。清单 9-48 包括了所有这些变化。

清单 9-48。ch9_10d.html

var options = {

title: 'Multiseries Line Chart',

轴任务:{

label: 'AxisLabel'

}

grid: {

background: '#000000'

gridLineColor: '#ffffff',

gridLineWidth: 2

},

axes: {

xaxis: {

numberTicks: 5,

min: 0,

max: 8

},

yaxis: {

numberTicks: 3,

min: 0,

max: 12

}

}

};

最后,你会得到一个带有所需网格的新图表(见图 9-40 )。

A978-1-4302-6290-9_9_Fig40_HTML.jpg

图 9-40。

A multiseries line chart with a customized grid

请注意,有一个灰色的轮廓界定了图表:边界。你也可以改变它,或者禁用它,如清单 9-49 所示。您也可以将drawBorder属性设置为'false'并禁用shadow

清单 9-49。ch9_20e.html

grid: {

drawBorder: false,

shadow: false,

gridLineColor: '#000000',

gridLineWidth: 2,

},

在这些改变之后,你获得了一个可读性更好的网格,如图 9-41 中的网格,它有一个与网格颜色相同的边框(白色)。

A978-1-4302-6290-9_9_Fig41_HTML.jpg

图 9-41。

A more readable multiseries line chart, with a customized grid

使用折线图上的区域

到目前为止,您已经看到了折线图基本上由线条连接的点集合组成,描述了一定规模的趋势。现在,你可能会发现这样的观点有些局限。通常,折线图最有趣的部分是一条线(或几条线)以某种方式划定的区域。

面积图

折线图可以转换成面积图。在这个例子中,你将使用你已经创建的多系列折线图(见清单 9-50),为了得到一个混合了区域和线条的新图表,你需要进行一些修改。在这里,您将看到只需做很少的更改就能达到预期的效果。

清单 9-50。ch9_22a.html

$(document).ready(function(){

var data1 = [1, 2, 3, 2, 3, 4];

var data2 = [3, 4, 5, 6, 5, 7];

var data3 = [5, 6, 8, 9, 7, 9];

var data4 = [7, 8, 9, 11, 10, 11];

var options = {

title:'Multiple Data Arrays'

};

$.jqplot ('myChart', [data1, data2, data3, data4], options);

});

首先,在options中,您必须将fill属性插入到您想要表示为区域的系列中。这一次,您选择seriesDefaults将区域表示应用于所有系列。这样,你就得到一个面积图。为了使图表更好,你可以添加其他选项,比如平滑(见清单 9-51)。

清单 9-51。ch9_22a.html

var options = {

title: 'Multiple Data Arrays',

seriesDefaults: {

showMarker: false,

rendererOptions: {

smooth: true

},

fill: true

}

};

但是,当运行该网页时,您立即发现有些不对劲:最后一个系列的区域覆盖了其他系列(见图 9-42 )。

A978-1-4302-6290-9_9_Fig42_HTML.jpg

图 9-42。

An area chart with one series covering the others

在对序列应用fill属性之前,您需要考虑序列中相应区域的表示顺序。在这种情况下,只需以不同的方式对序列进行排序:

$.jqplot ('myChart', [``data4, data3, data2, data1T2】

结果是一个精确的面积图,如图 9-43 所示。

A978-1-4302-6290-9_9_Fig43_HTML.jpg

图 9-43。

A multiseries area chart rendered correctly

折线图和面积图

在同一个图表中混合线条和区域也可以创造出非常好的效果。继续上一个例子(见清单 9-51),不要在seriesDefaults中设置fill属性,然后对所有序列应用填充,你可以决定逐个序列地这样做,以选择哪个序列必须表示为面积,哪个序列必须表示为线条,如清单 9-52 所示。

清单 9-52。ch9_22b.html

var options = {

title:'Multiple Data Arrays',

seriesDefaults: {

showMarker: false,

rendererOptions: {

smooth: true

}

},

series: [{}, {fill: true}, {}, {fill: true}]

};

9-44 显示了如何组合折线图和面积图。

A978-1-4302-6290-9_9_Fig44_HTML.jpg

图 9-44。

A combined line and area chart

波段图

带状图(也称为高低点折线图或范围图)是一种结合了面积图和折线图特征的图表。

带状图是一种增强了底层阴影区域的折线图(见图 9-45 )。该区域代表 y 轴上数值范围的上限和下限。这个范围随着 x 的变化而变化,最终,你会得到一个波段。

A978-1-4302-6290-9_9_Fig45_HTML.jpg

图 9-45。

A band chart

您可以使用一个带区来指示 y 轴上的特定区间,该区间随 x 轴上的值而变化,并与其内部的线条趋势相关联,例如,说明置信区间或误差带。另一个用途可能是突出显示随时间变化的分布和显示算术平均值的线。

使用 jqPlot,可以自动计算或手动分配波段。如果手动分配,则必须以两个[x,y]值数组的形式提供波段的边界。第一个数组限定了下限线;第二个数组,上界线。这两个数组作为另一个数组的两个元素连接在一起,传递给options中的bandData属性。

首先,让我们用[x,y]值对和波段数组bdata定义一个数据数组,包含两个数组:下界线和上界线(见清单 9-53)。

清单 9-53。ch9_24a.html

var data         = [[10,100],[20,110],[30,140],[40,130],

[50,80],[60,75],[70,120],[80,130],[90,100]];

varbdata =[ [[10,90],[20,100],[30,130],[40,120],

[50,70],[60,65],[70,110],[80,120],[90,90]],

[[10,110],[20,120],[30,150],[40,140],

[50,90],[60,85],[70,130],[80,140],[90,110]]];

然后,在options中,使用清单 9-54 所示的代码。图 9-46 展示了由此产生的带状线图。

清单 9-54。ch9_24a.html

var options = {

series: [{

rendererOptions: { bandData: bdata }

}],

seriesDefaults: {

shadow: false,

showMarker: false

}

};

$.jqplot ('myChart', [data], options);

A978-1-4302-6290-9_9_Fig46_HTML.jpg

图 9-46。

A banded-line chart

如果您选择绘制平滑折线图,波段也会变得平滑。清单 9-55 给出了代码,图 9-47 给出了结果。

清单 9-55。ch9_24b.html

rendererOptions: {

bandData: bdata,

smooth: true

}

A978-1-4302-6290-9_9_Fig47_HTML.jpg

图 9-47。

A smooth-banded-line chart

波段数据数组中的点数不必与数据序列中的点数相对应。此外,如果数据系列经过平滑处理,波段数据将被绘制为平滑线。该带不必相对于主线对称。通过在bdata数组中插入一个具有不对称 y 值的数组,可以使波段不对称,如清单 9-56 所示。

清单 9-56。ch9_24c.html

varbdata =[ [[10,90],[30,100],[40,100],[50,70],

[60,65], [70,110],[80,120],[90,90]],

[[10,110],[30,150],[40,140],[50,120],

[60,85], [70,130],[80,140],[90,110]] ];

现在,图 9-48 中的带相对于主线不对称。

A978-1-4302-6290-9_9_Fig48_HTML.jpg

图 9-48。

A nonuniform banded-line chart

但是,提供波段数据不是强制性的;它们可以由 jqPlot 自动计算。要激活这个特性而不使用任何数组,你必须将bands对象的show属性设置为rendererOptions中的'true',如清单 9-57 所示。如图 9-49 所示,默认情况下,波段间隔覆盖主线 y 值的+/-3%。

清单 9-57。ch9_24d.html

series: [{

rendererOptions: {

bands: { show: true},

smooth: true

}

}],

A978-1-4302-6290-9_9_Fig49_HTML.jpg

图 9-49。

A banded-line chart with a band interval of +/-3 percent

填充折线图中的线条

你刚刚了解了乐队。为什么不填充两条系列线之间的区域?甚至这个任务也可以用 jqPlot 来完成。通过设置fillBetween对象内的属性,可以控制图上两条线之间的区域。

在这里,你从一个非常简单的多系列折线图开始(同样的例子用于其他情况),如清单 9-58 所示。

清单 9-58。ch9_5a.html

$(document).ready(function(){

var data1 = [1, 2, 3, 2, 3, 4];

var data2 = [3, 4, 5, 6, 5, 7];

var data3 = [5, 6, 8, 9, 7, 9];

var data4 = [7, 8, 9, 11, 10, 11];

var options = {

title:'Multiple Data Arrays',

};

$.jqplot('myChart', [data1, data2, data3, data4], options);

});

使用此多系列折线图,您可以考虑每个系列,第一个系列的索引从 0 开始;1、为第二系列;2、为第三;诸如此类。

所以,如果你想填充两行之间的区域,你需要在series1series2属性中指定与它们对应的两个索引。例如,如果你想填充第二个和第四个系列之间的区域,你必须设置series1为 1(第二个系列)和series 2为 3(第四个系列),如清单 9-59 所示。可选地,您可以使用color属性或者更好地使用rgba()函数来设置分隔区域的颜色。

清单 9-59。ch9_25.html

var options = {

title: 'Multiple Data Arrays',

fillBetween: {

series1: 1,   //second series

series2: 3,   //fourth series

color: "rgba(10, 120, 130, 0.7)"

}

});

在图 9-50 中,您可以看到第二个和第四个系列之间的选定区域是彩色的。

A978-1-4302-6290-9_9_Fig50_HTML.jpg

图 9-50。

A multiseries line chart with a colored area between two lines

您可以将一个 JavaScript 函数绑定到一个按钮,用于更新每个系列的绘图设置,然后重新绘制所有内容。为此,让我们将清单 9-60 中的函数添加到 jQuery ready()函数中。

清单 9-60。ch9_26.html

$("button[name=changeFill]").click(function(e) {

plot1.fillBetween.series1 = parseInt($("input[name=series1]").val());

plot1.fillBetween.series2 = parseInt($("input[name=series2]").val());

plot1.replot();

});

为了让前面的 JavaScript 函数工作,您需要将函数$.jqplot()返回的值赋给变量plot1:

plot1 = $.jqplot ('myChart', [data1, data2, data3, data4], options);

并且,在网页的<body>部分,你必须添加两个输入文本区域和一个按钮,如清单 9-61 所示。

清单 9-61。ch9_26.html

<label for="series1">First Series: </label>

<input type="text" name="series1" value="1" />

<label for="series2"> Second Series: </label>

<input type="text" name="series2" value="3" />

<button name="changeFill">Change Fill</button>

结果如图 9-51 所示。

A978-1-4302-6290-9_9_Fig51_HTML.jpg

图 9-51。

A multiseries line chart with a selectable colored area

要用一个 jQuery UI 小部件替换简单的 HTML 控件,你必须对代码做一些修改以便集成它,如清单 9-62 所示。

清单 9-62。ch9_26ui.html

<link rel="stylesheet" href="../src/css/smoothness/jquery-ui-1.10.3.custom.min.css" />

<script src="../src/js/jquery-ui-1.10.3.custom.min.js"></script>

...

$("button[name=changeFill]").click(function(e) {

plot1.fillBetween.series1 = parseInt($("#combobox").val());

plot1.fillBetween.series2 = parseInt($("#combobox2").val());

plot1.replot();

});

...

<div class="ui-widget">

<label>First Series : </label>

<select id="combobox">

<option value="0">1</option>

<option value="1">2</option>

<option value="2">3</option>

<option value="3">4</option>

</select>

</div>

<div class="ui-widget">

<label>Second Series : </label>

<select id="combobox2">

<option value="0">1</option>

<option value="1">2</option>

<option value="2">3</option>

<option value="3">4</option>

</select>

</div>

<button name="changeFill">Change Fill</button>

<script>

$(function() {

$( 'button')

.button()

.click(function( event ) {

event.preventDefault();

});

});

</script>

结果就是图 9-52 所示的图表。

A978-1-4302-6290-9_9_Fig52_HTML.jpg

图 9-52。

A multiseries line chart with a selectable colored area

趋势线

jqPlot 真的是惊喜满满。除了你已经看到的关于折线图的所有东西,jqPlot 还可以计算和表示趋势线。这些通常是在图表中绘制的直线,但有时它们可以是指数的(如果它们在对数标度中是线性的)。趋势线表示图表中绘制的系列数据的一般模式或方向。这条线是用统计技术画出来的。这个功能由另一个插件执行:Trendline。

要启用此功能,您需要在网页中包含插件:

<script type="text/javascript" src="../src/plugins/jqplot.trendline.min.js"></script>

之后,您只需要激活插件,添加启用它的行,如清单 9-63 所示。

清单 9-63。ch9_27a.html

$(document).ready(function(){

var data = [100, 110, 140, 130, 135, 132, 140, 135, 142]

$.jqplot.config.enablePlugins = true;

$.jqplot ('myChart', [data]);

});

用这几条线可以得到一条趋势线,如图 9-53 所示。

A978-1-4302-6290-9_9_Fig53_HTML.jpg

图 9-53。

The linear trend line of a line chart

但是,如果您喜欢显式地表达这些属性,您可以通过使用选项来实现。这使您能够像处理图表中的其他对象一样处理趋势线。假设你想改变线条的颜色,增加线条的粗细,使其更加突出(见清单 9-64)。

清单 9-64。ch9_27b.html

var options = {

seriesDefaults: {

trendline: {

show:true,

color: '#ff0000',

lineWidth: 4

}

}

}

$.jqplot ('myChart', [data], options);

你现在对趋势线有了更多的控制。图 9-54 显示了trendline对象中带有属性设置的线条(趋势线较粗,在浏览器上显示为深红色)。

A978-1-4302-6290-9_9_Fig54_HTML.jpg

图 9-54。

A customized linear trend line in a line chart

如前所述,可以使用趋势线曲线,它表示图表中各点之后的指数趋势。让我们在清单 9-65 的下一个例子中检验这一点。

清单 9-65。ch9_28.html

$(document).ready(function(){

var data = [[10, 1.44], [30, 6.98], [50, 10.7], [70, 37.5], [90, 78.1]];

var options = {

seriesDefaults: {

trendline: {

show:true,

color: '#ff0000',

lineWidth: 4,

type: 'exponential'

}

}

}

$.jqplot ('myChart', [data], options);

});

9-55 显示了一个折线图,其中绘制了一系列遵循指数趋势的点。因此,你可以用指数趋势线来强调这一点。

A978-1-4302-6290-9_9_Fig55_HTML.jpg

图 9-55。

A customized exponential trend in a line chart

摘要

在这丰富的章节中,你已经精通 jqPlot 世界。您看到了这个库提供的许多可能性,使您能够尽最大能力实现折线图。您学习了如何操作绘制图表的基本元素,如轴和刻度。特别是,您看到了如何在同一个图表中管理多个数据系列(多系列图表),添加各种图形效果。您还探索了 jqPlot 库允许您操作不同格式的日期和时间值的方式。此外,您看到了如何使用 HTML 格式定制一些元素,以及突出显示数据点。在本章的最后一部分,你处理了更复杂的情况,比如生成趋势线和使用波段图。

在下一章,一个充满争论的章节,你将会面对其他新的概念,这次是应用在条形图上。