2016-10-02 3 views
1

Wir verwenden Kursdiagramm von AmCharts mit mehreren Datensätzen, die asynchron über Ajax geladen werden.AmCharts Kursdiagramm mehrfacher DataSets Datumsbereich ist falsch

Leider sieht es aus wie Datumsbereich für das gesamte Diagramm, damit meine ich "From" und "To" wird nur von dem ersten gesetzt, der dem Array aller DataSets hinzugefügt wird.

Stellen Situation, dass Sie 3 Dataset haben und jeder von ihnen kann vollständig Start- und Enddatum anders hat:

<script id="data-set-1" type="application/json"> 
     [ 
      {"date": "2016-10-02T10:00:00", "value": 23.8}, 
      {"date": "2016-10-02T10:05:00", "value": 16.8}, 
      {"date": "2016-10-02T10:10:00", "value": 20.5} 
     ] 
</script> 
<!-- This dataset has max end date from all 3 datasets --> 
<script id="data-set-2" type="application/json"> 
     [ 
      {"date": "2016-10-02T10:00:00", "value": 15.2}, 
      {"date": "2016-10-02T10:05:00", "value": 21.4}, 
      {"date": "2016-10-02T10:15:00", "value": 18.1} 
     ] 
</script> 
<!-- This dataset has min start date from all 3 datasets --> 
<script id="data-set-3" type="application/json"> 
     [ 
      {"date": "2016-10-02T09:55:00", "value": 12.4}, 
      {"date": "2016-10-02T10:00:00", "value": 17.7}, 
      {"date": "2016-10-02T10:05:00", "value": 14.6} 
     ] 
</script> 

In obigem Beispiel können Sie, dass die Daten-Set-2 siehe max Enddatum von allen 3 hat DataSets und data-set-3 hat ein Mindeststartdatum von allen 3 DataSets.

Das Endergebnis:

<!DOCTYPE html> 
 
<html> 
 
<head> 
 
    <title>AmCharts multiple datasets min-max date range issue</title> 
 
    <meta charset="utf-8" /> 
 
    <style type="text/css"> 
 
     #chartdiv { 
 
      width: 100%; 
 
      height: 500px; 
 
     } 
 
    </style> 
 
    <script id="data-set-1" type="application/json"> 
 
      [ 
 
       {"date": "2016-10-02T10:00:00", "value": 23.8}, 
 
       {"date": "2016-10-02T10:05:00", "value": 16.8}, 
 
       {"date": "2016-10-02T10:10:00", "value": 20.5} 
 
      ] 
 
    </script> 
 
    <!-- This dataset has max end date from all 3 datasets --> 
 
    <script id="data-set-2" type="application/json"> 
 
      [ 
 
       {"date": "2016-10-02T10:00:00", "value": 15.2}, 
 
       {"date": "2016-10-02T10:05:00", "value": 21.4}, 
 
       {"date": "2016-10-02T10:15:00", "value": 18.1} 
 
      ] 
 
    </script> 
 
    <!-- This dataset has min start date from all 3 datasets --> 
 
    <script id="data-set-3" type="application/json"> 
 
      [ 
 
       {"date": "2016-10-02T09:55:00", "value": 12.4}, 
 
       {"date": "2016-10-02T10:00:00", "value": 17.7}, 
 
       {"date": "2016-10-02T10:05:00", "value": 14.6} 
 
      ] 
 
    </script> 
 
    <link rel="stylesheet" href="https://www.amcharts.com/lib/3/plugins/export/export.css" type="text/css" media="all" /> 
 
</head> 
 
<body> 
 
    <div id="chartdiv"></div> 
 
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script> 
 
    <script src="https://www.amcharts.com/lib/3/amcharts.js"></script> 
 
    <script src="https://www.amcharts.com/lib/3/serial.js"></script> 
 
    <script src="https://www.amcharts.com/lib/3/amstock.js"></script> 
 
    <script src="https://www.amcharts.com/lib/3/plugins/export/export.min.js"></script> 
 
    <script type="text/javascript"> 
 

 
     $(document).ready(function() { 
 
      AmCharts.useUTC = true; // this will prevent adding timezone hours to ech date 
 

 
      var chart = AmCharts.makeChart("chartdiv", { 
 
       "pathToImages": "http://cdn.amcharts.com/lib/3/images/", 
 
       "type": "stock", 
 
       "theme": "light", 
 
       "categoryAxesSettings": { 
 
        "minPeriod": "mm" // precision to minutes 
 
       }, 
 

 
       "dataSets": [], // empty, we will add each based on single sensor 
 

 
       "panels": [{ 
 
        "recalculateToPercents": "never", // show value on scale not percent 
 
        "showCategoryAxis": true, 
 
        "title": "", 
 
        "percentHeight": 70, 
 

 
        "stockGraphs": [{ // generic config for all lines 
 
         "id": "g1", 
 
         "connect": true, // show gaps in data 
 
         "comparable": true, // must be true to disable/enable each dataset 
 
         "compareField": "value", 
 
         "valueField": "value", 
 
         "type": "smoothedLine", 
 
         "lineThickness": 2, 
 
         "bullet": "round" 
 
        }], 
 

 
        "stockLegend": { 
 
         "periodValueTextRegular": "[[value.close]]" // what will be shown at top legend 
 
        } 
 
       }], 
 

 
       "chartScrollbarSettings": { 
 
        "graph": "g1", 
 
        "usePeriod": "10mm", 
 
        "position": "top" 
 
       }, 
 

 
       "chartCursorSettings": { 
 
        "valueBalloonsEnabled": true 
 
       }, 
 

 
       "periodSelector": { 
 
        "fromText": "", 
 
        "toText": "", 
 
        "periodsText": "", 
 
        "position": "top", 
 
        "dateFormat": "YYYY-MM-DD JJ:NN", 
 
        "inputFieldWidth": 150, 
 
        "periods": [{ 
 
         "period": "hh", 
 
         "count": 1, 
 
         "label": "1 H", 
 
         "selected": true 
 
        }, { 
 
         "period": "hh", 
 
         "count": 8, 
 
         "label": "8 H" 
 
        }, { 
 
         "period": "DD", 
 
         "count": 1, 
 
         "label": "1 D" 
 
        }, { 
 
         "period": "DD", 
 
         "count": 10, 
 
         "label": "10 D" 
 
        }, { 
 
         "period": "MM", 
 
         "selected": true, 
 
         "count": 1, 
 
         "label": "1 M" 
 
        }, { 
 
         "period": "YYYY", 
 
         "count": 1, 
 
         "label": "1 Y" 
 
        }, { 
 
         "period": "YTD", 
 
         "label": "YTD" 
 
        }, { 
 
         "period": "MAX", 
 
         "label": "MAX" 
 
        }] 
 

 
       }, 
 

 
       "panelsSettings": { 
 
        "usePrefixes": true 
 
       }, 
 

 
       "export": { 
 
        "enabled": true, 
 
        "exportTitles": true, 
 
        "libs": { 
 
         "path": "http://www.amcharts.com/lib/3/plugins/export/libs/" 
 
        }, 
 
        "position": "bottom-right" 
 
       } 
 
      }); 
 

 
      for (var i = 1; i <= 3; i++) { 
 
       var dataset = new AmCharts.DataSet(); 
 
       dataset.compared = true; 
 
       dataset.title = "DataSet " + i; 
 
       dataset.categoryField = "date"; 
 
       dataset.fieldMappings = JSON.parse('[{"fromField": "value", "toField": "value"}]'); 
 

 
       var data = JSON.parse($("#data-set-" + i).html()); 
 
       dataset.dataProvider = data; 
 
       chart.dataSets.push(dataset); 
 
       chart.validateData(); 
 
      } 
 
     }); 
 
    </script> 
 
</body> 
 
</html>

Man kann sehen, dass das gesamte Diagramm zum Datumsbereich abgeschnitten wird aus Daten-Set-1, einem Diagramm ist nicht mit Datum-set-2-Punkt- :

{"date": "2016-10-02T10:15:00", "value": 18.1} 

und auch nicht Datum-set-3-Punkt zeigt:

{"date": "2016-10-02T09:55:00", "value": 12.4} 

Ich habe versucht zu hacken „From“ und „To“ Eingänge ohne Erfolg:

chart.addListener("init", 
    function (e) { 
     //e.chart.startDate = moment("2016-10-01 00:00"); 
     //e.chart.endDate = moment("2016-10-03 00:00"); 
    }); 

Irgendwelche Ideen, wie Diagramm zu zwingen, für minimale und maximale Daten aus allen Datasets zum Nachschlagen und nicht nur von der ersten Ein hinzugefügt zu dem Array von DataSets?

Antwort

1

Stock Chart verwendet immer den Bereich der Daten aus dem ausgewählten Hauptdatensatz und ignoriert Datenpunkte von verglichenen Datensätzen, die nicht in diesen Bereich passen.

Außerdem ignoriert es Datenpunkte, die keine direkte Zeitstempelübereinstimmung haben.

Die naheliegende Lösung besteht darin, die Daten in allen Datensätzen durch Hinzufügen "leerer" Datenpunkte im Hauptdatensatz zu synchronisieren, die sich mit denen in verglichenen Datensätzen überschneiden würden.

Ich weiß, es könnte frustrierend ungünstig und ineffizient sein, dies auf der Serverseite zu tun, wo Daten erzeugt werden.

Glücklicherweise können wir einen clientseitigen Wrapper implementieren, der das tun würde.

<!DOCTYPE html> 
 
<html> 
 
<head> 
 
    <title>AmCharts multiple datasets min-max date range issue</title> 
 
    <meta charset="utf-8" /> 
 
    <style type="text/css"> 
 
     #chartdiv { 
 
      width: 100%; 
 
      height: 500px; 
 
     } 
 
    </style> 
 
    
 
    <script id="data-set-1" type="application/json"> 
 
      [ 
 
       {"date": "2016-10-02T10:00:00", "value": 23.8}, 
 
       {"date": "2016-10-02T10:05:00", "value": 16.8}, 
 
       {"date": "2016-10-02T10:10:00", "value": 20.5} 
 
      ] 
 
    </script> 
 
    <!-- This dataset has max end date from all 3 datasets --> 
 
    <script id="data-set-2" type="application/json"> 
 
      [ 
 
       {"date": "2016-10-02T10:00:00", "value": 15.2}, 
 
       {"date": "2016-10-02T10:05:00", "value": 21.4}, 
 
       {"date": "2016-10-02T10:15:00", "value": 18.1} 
 
      ] 
 
    </script> 
 
    <!-- This dataset has min start date from all 3 datasets --> 
 
    <script id="data-set-3" type="application/json"> 
 
      [ 
 
       {"date": "2016-10-02T09:55:00", "value": 12.4}, 
 
       {"date": "2016-10-02T10:00:00", "value": 17.7}, 
 
       {"date": "2016-10-02T10:05:00", "value": 14.6} 
 
      ] 
 
    </script> 
 
    <link rel="stylesheet" href="https://www.amcharts.com/lib/3/plugins/export/export.css" type="text/css" media="all" /> 
 
</head> 
 
<body> 
 
    <div id="chartdiv"></div> 
 
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script> 
 
    <script src="https://www.amcharts.com/lib/3/amcharts.js"></script> 
 
    <script src="https://www.amcharts.com/lib/3/serial.js"></script> 
 
    <script src="https://www.amcharts.com/lib/3/amstock.js"></script> 
 
    <script src="https://www.amcharts.com/lib/3/plugins/export/export.min.js"></script> 
 
    <script type="text/javascript"> 
 
     function syncDataTimestamps(chart) { 
 

 
      // check if plugin is enabled 
 
      if (chart.syncDataTimestamps !== true) 
 
      return; 
 

 
      // go thorugh all data sets and collect all the different timestamps 
 
      var dates = {}; 
 
      for (var i = 0; i < chart.dataSets.length; i++) { 
 
      var ds = chart.dataSets[i]; 
 
      for (var x = 0; x < ds.dataProvider.length; x++) { 
 
       var date = ds.dataProvider[x][ds.categoryField]; 
 
       if (!(date instanceof Date)) 
 
       date = new Date(date); 
 
       if (dates[date.getTime()] === undefined) 
 
       dates[date.getTime()] = {}; 
 
       dates[date.getTime()][i] = ds.dataProvider[x]; 
 
      } 
 
      } 
 
      
 
      // iterate through data sets again and fill in the blanks 
 
      for (var i = 0; i < chart.dataSets.length; i++) { 
 
      var ds = chart.dataSets[i]; 
 
      var dp = []; 
 
      for (var ts in dates) { 
 
       if (!dates.hasOwnProperty(ts)) 
 
       continue; 
 
       var row = dates[ts]; 
 
       if (row[i] === undefined) { 
 
       row[i] = {}; 
 
       var d = new Date(); 
 
       d.setTime(ts); 
 
       row[i][ds.categoryField] = d; 
 
       } 
 
       dp.push(row[i]); 
 
      } 
 
      dp.sort(function(a,b){ 
 
       return new Date(a[ds.categoryField]) - new Date(b[ds.categoryField]); 
 
      }); 
 
      ds.dataProvider = dp; 
 
      } 
 

 
     }; 
 

 
     $(document).ready(function() { 
 
      AmCharts.useUTC = true; // this will prevent adding timezone hours to ech date 
 

 
      var chart = AmCharts.makeChart("chartdiv", { 
 
       "type": "stock", 
 
       "theme": "light", 
 
       "categoryAxesSettings": { 
 
        "minPeriod": "mm" // precision to minutes 
 
       }, 
 

 
       "syncDataTimestamps": true, 
 
       "dataSets": [], // empty, we will add each based on single sensor 
 

 
       "panels": [{ 
 
        "recalculateToPercents": "never", // show value on scale not percent 
 
        "showCategoryAxis": true, 
 
        "title": "", 
 
        "percentHeight": 70, 
 

 
        "stockGraphs": [{ // generic config for all lines 
 
         "id": "g1", 
 
         "connect": true, // show gaps in data 
 
         "comparable": true, // must be true to disable/enable each dataset 
 
         "compareField": "value", 
 
         "valueField": "value", 
 
         "type": "smoothedLine", 
 
         "lineThickness": 2, 
 
         "bullet": "round" 
 
        }], 
 

 
        "stockLegend": { 
 
         "periodValueTextRegular": "[[value.close]]" // what will be shown at top legend 
 
        } 
 
       }], 
 

 
       "chartScrollbarSettings": { 
 
        "graph": "g1", 
 
        "usePeriod": "10mm", 
 
        "position": "top" 
 
       }, 
 

 
       "chartCursorSettings": { 
 
        "valueBalloonsEnabled": true 
 
       }, 
 

 
       "periodSelector": { 
 
        "fromText": "", 
 
        "toText": "", 
 
        "periodsText": "", 
 
        "position": "top", 
 
        "dateFormat": "YYYY-MM-DD JJ:NN", 
 
        "inputFieldWidth": 150, 
 
        "periods": [{ 
 
         "period": "hh", 
 
         "count": 1, 
 
         "label": "1 H", 
 
         "selected": true 
 
        }, { 
 
         "period": "hh", 
 
         "count": 8, 
 
         "label": "8 H" 
 
        }, { 
 
         "period": "DD", 
 
         "count": 1, 
 
         "label": "1 D" 
 
        }, { 
 
         "period": "DD", 
 
         "count": 10, 
 
         "label": "10 D" 
 
        }, { 
 
         "period": "MM", 
 
         "selected": true, 
 
         "count": 1, 
 
         "label": "1 M" 
 
        }, { 
 
         "period": "YYYY", 
 
         "count": 1, 
 
         "label": "1 Y" 
 
        }, { 
 
         "period": "YTD", 
 
         "label": "YTD" 
 
        }, { 
 
         "period": "MAX", 
 
         "label": "MAX" 
 
        }] 
 

 
       }, 
 

 
       "panelsSettings": { 
 
        "usePrefixes": true 
 
       }, 
 

 
       "export": { 
 
        "enabled": true, 
 
        "exportTitles": true, 
 
        "libs": { 
 
         "path": "http://www.amcharts.com/lib/3/plugins/export/libs/" 
 
        }, 
 
        "position": "bottom-right" 
 
       } 
 
      }); 
 

 
      for (var i = 1; i <= 3; i++) { 
 
       var dataset = new AmCharts.DataSet(); 
 
       dataset.compared = true; 
 
       dataset.title = "DataSet " + i; 
 
       dataset.categoryField = "date"; 
 
       dataset.fieldMappings = JSON.parse('[{"fromField": "value", "toField": "value"}]'); 
 

 
       var data = JSON.parse($("#data-set-" + i).html()); 
 
       dataset.dataProvider = data; 
 
       chart.dataSets.push(dataset); 
 
      } 
 

 
      syncDataTimestamps(chart); 
 
      chart.validateData(); 
 
     }); 
 
    </script> 
 
</body> 
 
</html>

Bitte beachten Sie, dass ich ausgezogen auch den aus der Schleife validateData() Anruf, so dass es nur einmal aufgerufen wird, anstatt unnötig dreimal:

ich dein Beispiel hier aktualisiert .

+0

Und was ist mit Leistung, wenn wir viele Daten haben? –

+0

Ich nehme an, dass für einige hundert oder tausend Datenpunkte der zusätzliche Verarbeitungsaufwand keinen merklichen Unterschied machen sollte. Für Zehntausende oder Hunderttausende könnte es länger dauern.Aber es ist schwer, genaue Zahlen zu schätzen, nur müssen Sie es mit Ihren tatsächlichen Daten versuchen. – martynasma

+0

Fair genug für jetzt. Nachdem wir es in unserem Startup für einen großen Maßstab verwenden werden, werde ich meine Frage aktualisieren oder zusätzliche Antwort hinzufügen. Vielen Dank. –