如何画Flot堆栈折线图、堆栈柱形图和堆栈条形图

当你有多组数据需要看到随着时间变化的趋势走向又需要看各组数据的累加总和时,这时候选择用堆栈图来呈现是最适合的,除了上述的优点外,堆栈图还可以看各组数据的大小比例.这里我们用了3个网站的一个月内DNS查询次数来作范例数据.

堆栈图范例 (DNS Query)

堆栈图数据

因为Flot不支持堆栈图,所以必须加入堆栈图的插件jquery.flot.stack.js,此范例会用到的档案清单如下.
   
<script type="text/javascript" src="/js/jquery-1.8.3.min.js"></script>      
<!--[if lte IE 8]><script language="javascript" type="text/javascript" src="/js/flot/excanvas.min.js"></script><![endif]-->   
<script type="text/javascript" src="/js/flot/jquery.flot.js"></script>
<script type="text/javascript" src="/js/flot/jquery.flot.axislabels.js"></script>
<script type="text/javascript" src="/js/flot/jquery.flot.stack.js"></script>
<script type="text/javascript" src="/js/flot/jshashtable-2.1.js"></script>    
<script type="text/javascript" src="/js/flot/jquery.numberformatter-1.2.3.min.js"></script>
        
接着我们将网站的DNS查询数据建立成如下的数组格式,因为我们是用时间格式数据,所以建立了一个gd()函式用来取得javascript timestamps.这个范例我们用了3笔资料,为了简化说明,我们这里只显示1笔数据出来,后面2笔资料格式都是一样的,数据格式程序代码如下.
   
    var data = [
        [gd(2012, 1, 1), 208557], [gd(2012, 1, 2), 125068], [gd(2012, 1, 3), 931208], [gd(2012, 1, 4), 450040], 
        [gd(2012, 1, 5), 761180], [gd(2012, 1, 6), 744526], [gd(2012, 1, 7), 707095], [gd(2012, 1, 8), 601316],
        [gd(2012, 1, 9), 187495], [gd(2012, 1, 10), 716189], [gd(2012, 1, 11), 587141], [gd(2012, 1, 12), 147266], 
        [gd(2012, 1, 13), 574670], [gd(2012, 1, 14), 175881], [gd(2012, 1, 15), 272519], [gd(2012, 1, 16), 211131],
        [gd(2012, 1, 17), 637015], [gd(2012, 1, 18), 794050], [gd(2012, 1, 19), 399010], [gd(2012, 1, 20), 799942], 
        [gd(2012, 1, 21), 595768], [gd(2012, 1, 22), 717126], [gd(2012, 1, 23), 414923], [gd(2012, 1, 24), 462479],
        [gd(2012, 1, 25), 674334], [gd(2012, 1, 26), 20312], [gd(2012, 1, 27), 675892], [gd(2012, 1, 28), 808655], 
        [gd(2012, 1, 29), 194543], [gd(2012, 1, 30), 664716], [gd(2012, 1, 31), 980720]
    ];

    function gd(year, month, day) {
        return new Date(year, month - 1, day).getTime();
    }
        

堆栈图选项

当你要画堆栈图时需要设定series.stack为true,这样Flot就会以堆栈图呈现,另外我们做的是堆栈折线图,我们可以设定series.lines.fill为true,让图表用颜色填满区块,程序代码如下.
   
    series: {
        stack: true,
        lines: {
            show: true,
            fill: true
        }
    }
        
x轴和y轴部份我们一样在<head>里加入jquery.flot.axislabels.js档案后用设定axis.axisLabel设定轴标签名称还有其它如字号及字型样式等,因为我们是用时间格式数据,所以xaxis.mode必须设定用"time",因为数据是抓一个月份的数据,所以xaxis.tickSize设定成[3, "day"],3表示刻度卷标以每隔3天显示,而"day"而表示以日期显示,xaxis.tickLength我们设定为10,表示刻度线以高度10像素来显示.而axis.color设定成"black",这表示刻度标签的颜色,因为Flot默认的标签颜色为灰色的,我们改成黑色的比较明显.

另外yaxis.tickFormatter用来自行定义刻度标签的格式.x轴及y轴选项程序代码如下.
   
    xaxis: {
        mode: "time",
        tickSize: [3, "day"],
        tickLength: 10,
        color: "black",
        axisLabel: "Date",
        axisLabelUseCanvas: true,
        axisLabelFontSizePixels: 12,
        axisLabelFontFamily: 'Verdana, Arial',
        axisLabelPadding: 10
    }

    yaxis: {
        color: "black",
        axisLabel: "DNS Query Count",
        axisLabelUseCanvas: true,
        axisLabelFontSizePixels: 12,
        axisLabelFontFamily: 'Verdana, Arial',
        axisLabelPadding: 3,
        tickFormatter: function (v, axis) {
            return $.formatNumber(v, { format: "#,###", locale: "us" });
        }
    }
        
选项的最后我们设定了网格的选项,因为我们有用到提示框的功能,所以grid.hoverable必须设为true才能显示,此外我们还设定了图表外框宽度grid.borderWidth,以及背景使用渐层色呈现grid.backgroundColor.
   
    grid: {
        hoverable: true,
        borderWidth: 2,        
        backgroundColor: { colors: ["#EDF5FF", "#ffffff"] }
    }
        

完成堆栈图

最后一样呼叫$.plot函式把数据及选项带进去即完成.当你在画堆栈折线图时,其实就是把折线图画出来后设定series.stack:true及series.lines.fill:true而已,相信不会太难.下面我们还会介绍堆栈柱形图及堆栈条形图.
   
    $(document).ready(function () {
        $.plot($("#flot-placeholder"), dataset, options);
        $("#flot-placeholder").UseTooltip();
    });
        

堆栈图柱形图

堆栈柱形图范例 (DNS Query)
我们沿用上面堆栈折线图的程序代码,改成堆栈柱形图,只需要改选项里的几个地方,第一个将series.lines改成series.bars,然后只留下show属性,另外再加上bars.align设定成"center"让条图对齐中央,还有bars.barWidth设定成24 * 60 * 60 * 600, 为什么这样设定barWidth,因为我们x轴是用时间格式数据的,也就是以毫秒为单位,所以24 * 60 * 60 * 1000就等于一天,不过最后我们是乘以600不是1000,因为我们不想让条图相互贴在一起,让条图之间留点空隙看起来比较好看.
   
    series: {
        stack: true,
        bars: {
            show: true
        }
    }

    bars: {
        align: "center",
        barWidth:24 * 60 * 60 * 600
    }
        

堆栈图条形图

堆栈条形图范例 (DNS Query)
条形图就需要点功夫了,因为条形图是y轴显示时间,x轴为数字,首先你要先把数据建立出来如下.
   
    var data = [
        [569106, gd(2012, 1, 1)], [743944, gd(2012, 1, 2)], [120865, gd(2012, 1, 3)], [890208, gd(2012, 1, 4)], 
        [259723, gd(2012, 1, 5)], [177150, gd(2012, 1, 6)], [32430, gd(2012, 1, 7)], [274054, gd(2012, 1, 8)],
        [63435, gd(2012, 1, 9)], [994514, gd(2012, 1, 10)], [885453, gd(2012, 1, 11)], [289791, gd(2012, 1, 12)],
        [411717, gd(2012, 1, 13)], [95324, gd(2012, 1, 14)], [646479, gd(2012, 1, 15)], [448868, gd(2012, 1, 16)],
        [669678, gd(2012, 1, 17)], [909944, gd(2012, 1, 18)], [675965, gd(2012, 1, 19)], [281272, gd(2012, 1, 20)], 
        [629781, gd(2012, 1, 21)], [330138, gd(2012, 1, 22)], [802835, gd(2012, 1, 23)], [139079, gd(2012, 1, 24)],
        [187101, gd(2012, 1, 25)], [354332, gd(2012, 1, 26)], [361090, gd(2012, 1, 27)], [78171, gd(2012, 1, 28)],
        [452212, gd(2012, 1, 29)], [404369, gd(2012, 1, 30)], [63509, gd(2012, 1, 31)]
    ];
        
接着设定bars.horizontal为true,若这里没设定就会显示成柱形图,然后再设定yaxis.mode为"time",表示y轴以时间格式显示,另外我们还设定了yaxis.min及yaxis.max,如此可限制y轴刻度显示的最大及最小值.完整的选项程序代码如下.
   
    var options2 = {
        series: {
            stack: true,
            bars: {
                show: true
            }
        },
        bars: {
            lineWidth: 1,
            barWidth: 24 * 60 * 60 * 450,
            horizontal: true
        },
        xaxis: {
            color: "black",
            axisLabel: "Date",
            axisLabelUseCanvas: true,
            axisLabelFontSizePixels: 12,
            axisLabelFontFamily: 'Verdana, Arial',
            axisLabelPadding: 10,
            tickFormatter: function (v, axis) {
                return $.formatNumber(v, { format: "#,###", locale: "us" });
            }
        },
        yaxis: {
            mode: "time",
            tickSize: [3, "day"],
            min: gd(2012, 1, 1),
            max: gd(2012, 1, 31),
            tickLength: 10,        
            color: "black",
            axisLabel: "DNS Query Count",
            axisLabelUseCanvas: true,
            axisLabelFontSizePixels: 12,
            axisLabelFontFamily: 'Verdana, Arial',
            axisLabelPadding: 3
        },
        grid: {
            hoverable: true,
            borderWidth: 2,
            backgroundColor: { colors: ["#EDF5FF", "#ffffff"] }
        }
    };
        

练习

本章的完整范例程序代码可以在这里找到并做在线练习 Go to Example Tester