如何画Flot条形图

条形图和柱形图一样常被用来比较各组数据的相互关系, 差别在于条形图的长度越长, 所代表的值越大. 使用条形图的时机在于如果你有非常多组数据要放在一起比较, 这时用柱形图的话, 图表的宽度就有可能超出屏幕宽度, 所以改用条形图后会不断延伸的就是高度, 也方便使用者能够一眼就看到整张图表.

本章用贵金属价格, 黄金、白金、白银及钯金的现价当作数据, 另外还会介绍如何控条图的渐层色, 及控制图表图例的位置.


条形图范例(贵金属价格)

条形图资料

一开始不免俗的一样是放置定位点, 并且指定宽度和高度, 你可以直在用style设定, 或是指定一个CSS class给定位点.
   
        <style type="text/css">
        .mychart{
           width:300px;
           height:150px;
        }
        </style>
        <div id="flot-placeholder" class="mychart"></div>
        
这次数据我们只有7笔, 先建立一个叫rawData的数组变量, 再把数据放进去. 还记得之前章节里的数据格式吗? 是像这样的 [x, y],  我们以x轴放入时间格式数据(1325347200000, 1328025600000, ...), 或是按序号编码(0, 1, 2, ....), 而y轴则放入数据的数值, 但这次我们做的是条形图, x轴和y轴数据位置必须对调如下面的rawData变量. 你可以看到数组里的第一组数字是1582.3, 这个是金价, 而第二组数字就是序号.
   
        var rawData = [
            [1582.3, 0], //Gold
            [28.95, 1],  //Silver
            [1603, 2],   //Platinum
            [774, 3],    //Palladium
            [1245, 4],  //Rhodium
            [85, 5],      //Ruthenium 
            [1025, 6]    //Iridium 
        ];

        var dataSet = [
            { label: "Precious Metal Price", data: rawData, color: "#AB5800" }
        ];
        
接着就是要建立刻度数据, 可能有人会认为因为我们做的是条形图, x轴和y轴数据对调了, 所以刻度数据也要跟着对调. 答案是错的, 刻度数据并不需要跟着对调.
   
        var ticks = [
            [0, "Gold"], [1, "Silver"], [2, "Platinum"], [3, "Palldium"], [4, "Rhodium"], [5, "Ruthenium"], [6, "Iridium"]
        ];
        

条形图选项

当你绘制条形图时, bars.horizontal必须设定为true, 若没有设定, 就会变成柱形图. 在此范例里我们设定了bars.fillColor, 这属性可以接受的值可以是单一颜色(如rgba(255, 255, 255, 0.8))或是渐层色, 我们用的是后者. Flot里指定渐层色的方法可以是
   
        { colors: [ color1, color2, ... ] }
        
或是调整颜色的透明度如
   
        { colors: [ { opacity: 0.8 }, { opacity: 0.1 } ] }
        
另外我们还设定了bars.iineWidth, lineWidth是以像素为单位的线或轮廓的厚度, 在这范例里我们设成1, bars的完整选项程序代码如下
   
        bars: {
            align: "center",
            barWidth: 0.5,
            horizontal: true,
            fillColor: { colors: [{ opacity: 0.5 }, { opacity: 1}] },
            lineWidth: 1
        }
        
我们所用的数据中, 价格最贵的是白金为$1,603美金, 所以图表会以白金的条图做为宽度, 但如果我们想要让白金的条图不要占满整张图表的宽度的话, 就可以设定axis.max, 我们这在这设定2000, 如此一来白金的条图部份就不会占满整个宽度, 你也可以设定axis.min, 作用与max相反. axis.tickColor是设定网格线的颜色, 若不设定的话Flot会自动生成并且带一些透明度为基色, axis.color则是设定刻度标签的颜色.

在此我们为了美化刻度标签的格式, 我们用了jQuery Number Formatter外挂, 让x轴的值输出成货币格式, 要改变刻度标签可以复写axis.tickFormatter, 此函式传入了2个参数, tick value和axis object, 并且会传回字符串. 而Number Formatter可以到此下载.

而axis.axisLabel则是设定轴卷标, 此功能也是需要加入插件jquery.flot.axislabels.js才能使用.
以下是轴选项的程序代码
   
        xaxis: {
            axisLabel: "Price (USD/oz)",
            axisLabelUseCanvas: true,
            axisLabelFontSizePixels: 12,
            axisLabelFontFamily: 'Verdana, Arial',
            axisLabelPadding: 10,
            max: 2000,
            tickColor: "#5E5E5E",                        
            tickFormatter: function (v, axis) {
                return $.formatNumber(v, { format: "#,###", locale: "us" });            
            },
            color:"black"
        }

        yaxis: {
            axisLabel: "Precious Metals",
            axisLabelUseCanvas: true,
            axisLabelFontSizePixels: 12,
            axisLabelFontFamily: 'Verdana, Arial',
            axisLabelPadding: 3,
            tickColor: "#5E5E5E",        
            ticks: ticks, 
            color:"black"
        }
        
Flot的图例是自动产生的,不过你也可以控制图例的细节,预设图例会出现在右上角,不过有时候会挡到图表,你可以设定legend.position让图例出现在4个角落的其中一个,可设定的值有"ne"、"nw"、"se"和"sw",分别代表右上角(north east)、左上角(north west)、右下角(south east)和左下角(south west). legend.noColumns代表图例的table会被分成多少行,若设为0则表示只会分成单一一行. legend.labelBoxBorderColor则是设定图例标签盒边框的颜色.
   
        legend: {
            noColumns: 0,
            labelBoxBorderColor: "#858585",
            position: "ne"
        }
        

呼叫$.plot完成绘图

最后把上面建立的dataSet以及options带入$.plot, 就完成了!
   
        $(document).ready(function () {
            $.plot($("#flot-placeholder"), dataSet, options);    
            $("#flot-placeholder").UseTooltip();
        });
        
在此范例里有用了提示框, 这部份在往后会有专属的一章讲解, 在此就不详细说明.

本范例完整程序代码

   
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="/js/lib/jquery-1.8.3.min.js" type='text/javascript'></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.min.js"></script>        
    <script type="text/javascript" src="/js/flot/jquery.flot.axislabels.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> 
    <script type="text/javascript">
        //******* Precious Metal Price - HORIZONTAL BAR CHART
        var rawData = [[1582.3, 0], [28.95, 1],[1603, 2],[774, 3],[1245, 4], [85, 5],[1025, 6]];
        var dataSet = [{ label: "Precious Metal Price", data: rawData, color: "#E8E800" }];
        var ticks = [[0, "Gold"], [1, "Silver"], [2, "Platinum"], [3, "Palldium"], [4, "Rhodium"], [5, "Ruthenium"], [6, "Iridium"]];

        var options = {
            series: {
                bars: {
                    show: true
                }
            },
            bars: {
                align: "center",
                barWidth: 0.5,
                horizontal: true,
                fillColor: { colors: [{ opacity: 0.5 }, { opacity: 1}] },
                lineWidth: 1
            },
            xaxis: {
                axisLabel: "Price (USD/oz)",
                axisLabelUseCanvas: true,
                axisLabelFontSizePixels: 12,
                axisLabelFontFamily: 'Verdana, Arial',
                axisLabelPadding: 10,
                max: 2000,
                tickColor: "#5E5E5E",
                tickFormatter: function (v, axis) {
                    return $.formatNumber(v, { format: "#,###", locale: "us" });
                },
                color: "black"
            },
            yaxis: {
                axisLabel: "Precious Metals",
                axisLabelUseCanvas: true,
                axisLabelFontSizePixels: 12,
                axisLabelFontFamily: 'Verdana, Arial',
                axisLabelPadding: 3,
                tickColor: "#5E5E5E",
                ticks: ticks,
                color: "black"
            },
            legend: {
                noColumns: 0,
                labelBoxBorderColor: "#858585",
                position: "ne"
            },
            grid: {
                hoverable: true,
                borderWidth: 2,
                backgroundColor: { colors: ["#171717", "#4F4F4F"] }
            }
        };

        $(document).ready(function () {
            $.plot($("#flot-placeholder"), dataSet, options);
            $("#flot-placeholder").UseTooltip();
        });

        var previousPoint = null, previousLabel = null;

        $.fn.UseTooltip = function () {
            $(this).bind("plothover", function (event, pos, item) {
                if (item) {
                    if ((previousLabel != item.series.label) ||
                 (previousPoint != item.dataIndex)) {
                        previousPoint = item.dataIndex;
                        previousLabel = item.series.label;
                        $("#tooltip").remove();

                        var x = item.datapoint[0];
                        var y = item.datapoint[1];

                        var color = item.series.color;
                        //alert(color)
                        //console.log(item.series.xaxis.ticks[x].label);                

                        showTooltip(item.pageX,
                        item.pageY,
                        color,
                        "<strong>" + item.series.label + "</strong><br>" + item.series.yaxis.ticks[y].label +
                        " : <strong>" + $.formatNumber(x, { format: "#,###", locale: "us" }) + "</strong> USD/oz");
                    }
                } else {
                    $("#tooltip").remove();
                    previousPoint = null;
                }
            });
        };

        function showTooltip(x, y, color, contents) {
            $('<div id="tooltip">' + contents + '</div>').css({
                position: 'absolute',
                display: 'none',
                top: y - 10,
                left: x + 10,
                border: '2px solid ' + color,
                padding: '3px',
                'font-size': '9px',
                'border-radius': '5px',
                'background-color': '#fff',
                'font-family': 'Verdana, Arial, Helvetica, Tahoma, sans-serif',
                opacity: 0.9
            }).appendTo("body").fadeIn(200);
        }
    </script>
</head>
<body>
    <div style="width:450px;height:300px;text-align:center;margin:10px">        
        <div id="flot-placeholder" style="width:100%;height:100%;"></div>        
    </div>
</body>
</html>
        

练习

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