为什么jqPlot显示错误的饼图,其中包含通过AJAX检索的数据?

时间:2015-03-24 22:39:52

标签: jquery ajax jqplot

我正在开发一个应用程序,我在其中使用jqPlot使用通过AJAX检索的一些数据绘制饼图。但是,我注意到生成的饼图是错误的。 当我手动将数据放入数组时,饼图是正确的。

这是我的代码的一部分。

  $.ajax({
    url:'http://localhost/mijson.php',
    dataType:'json',
    async:false,
    success:function(data){
        for(a in data){
            var div_pintar = "<div id='divgrafica"+a+"' class='myChart'></div>";
            $("#espacio_graficas").append(div_pintar);
            var datos_tmp = [];
            datos_tmp.push(['Ok',data[a]['ok']]);
            datos_tmp.push(['Fail',data[a]['fail']]);

            $.jqplot('divgrafica'+a, [datos_tmp], {
                title:data[a]['label'] ,
                seriesDefaults:{
                    renderer:$.jqplot.PieRenderer,
                    trendline:{ show: true },
                },
                legend:{ show: true }
            });
            ...

我得到的JSON是这样的:

[{"label":"FECHA","requer":56,"ok":28,"fail":28},
 {"label":"TTM Y FECHA","requer":35,"ok":8,"fail":27}]

总之,它向我展示了一个饼图,例如,有两个值,但是添加的是14%。

如果我使用ajaxDataRenderer

,也会出现同样的情况
...
    plo12 = $.jqplot('pieChart2', jsonurl,{
        title: 'AJAX JSON Data Renderer',
        dataRenderer: ajaxDataRenderer,
        seriesDefaults: {
            renderer: $.jqplot.PieRenderer,
            rendererOptions: {
                showDataLabels: true
            }
        },
        legend: { show: true, location: 'e' }
    });
    ...

2 个答案:

答案 0 :(得分:1)

如果没有更多信息,很难确定您的问题究竟是什么。

然而,导致错误图表的最明显的事情是使用:

for(a in data){

解析由AJAX success:function返回的JSON object,实际上是array

$.ajax({
    success:function(data){

引用"for...in" page on MDN

  

数组迭代和for ... in
  注意:for..in不应该用于迭代索引顺序很重要的数组。

     

数组索引只是具有整数名称的可枚举属性,并且与一般对象属性相同。 无法保证for ... in将以任何特定顺序返回索引它将返回所有可枚举属性,包括具有非整数名称和那些被遗传的

     

因为迭代的顺序是依赖于实现的,所以迭代数组可能不会以一致的顺序访问元素。因此,当迭代访问顺序很重要的数组时,最好使用带有数字索引(或Array.forEach或for ... of循环)的for循环。

在这种情况下,顺序非常重要,因为无论使用何种浏览器,您都希望图表的显示顺序相同。因此,您应该以确定的方式处理数组的成员。

更重要的是:

  

仅对自有属性进行迭代

     

如果您只想考虑附加到对象本身的属性,而不是其原型,请使用getOwnPropertyNames或执行hasOwnProperty检查(propertyIsEnumerable也可以使用)。或者,如果您知道不会有任何外部代码干扰,您可以使用检查方法扩展内置原型。

每个数组都具有与其原型相关联的属性,而不仅仅是数组的成员。通过使用for(a in data){},在没有任何限定的情况下将这些包括在您的处理中,几乎可以保证导致错误的显示。

对代码进行编码的另一种方法是使用forEach()

  $.ajax({
    url:'http://localhost/mijson.php',
    dataType:'json',
    async:false,
    success:function(data){
        data.forEach(function(curObject, a) {
            var div_pintar = "<div id='divgrafica"+a+"' class='myChart'></div>";
            $("#espacio_graficas").append(div_pintar);
            var datos_tmp = [];
            datos_tmp.push(['Ok',data[a]['ok']]);
            datos_tmp.push(['Fail',data[a]['fail']]);

            $.jqplot('divgrafica'+a, [datos_tmp], {
                title:data[a]['label'] ,
                seriesDefaults:{
                    renderer:$.jqplot.PieRenderer,
                    trendline:{ show: true },
                },
                legend:{ show: true }
            });
            ...

注意:我通常会将所有data[a]引用更改为curObject,但不这样做会起作用(数组索引作为a传入)并且结果最少您的代码更改。进行其他更改应该使代码稍微快一些,因为不必多次查找数组。

通过这些更改并使用更具描述性的index代替a,代码如下所示:

  $.ajax({
    url:'http://localhost/mijson.php',
    dataType:'json',
    async:false,
    success:function(data){
        data.forEach(function(curObject, index) {
            var div_pintar = "<div id='divgrafica"+index+"' class='myChart'></div>";
            $("#espacio_graficas").append(div_pintar);
            var datos_tmp = [];
            datos_tmp.push(['Ok',curObject['ok']]);
            datos_tmp.push(['Fail',curObject['fail']]);

            $.jqplot('divgrafica'+index, [datos_tmp], {
                title:curObject['label'] ,
                seriesDefaults:{
                    renderer:$.jqplot.PieRenderer,
                    trendline:{ show: true },
                },
                legend:{ show: true }
            });
            ...

答案 1 :(得分:1)

感谢Makyen帮助我,虽然答案很好,但错误仍然存​​在。 经过16个小时的尝试,我找到了解决方案,非常非常容易。

 .....
     var div_pintar = "<div id='divgrafica"+index+"' class='myChart'></div>";
                $("#espacio_graficas").append(div_pintar);
                var datos_tmp = [];
                    datos_tmp.push(['Ok',parseInt(datos[a]['ok'])]);
                    datos_tmp.push(['Fail',parseInt(datos[a]['fail'])]);
    ......

仅限使用javascript parseInt

的功能

我希望这对其他人有帮助。 我失去了很多时间:(