Uncaught TypeError: dp[ds.categoryField].setFullYear is not a function at Object.AmCharts.baseYearInitialize

Uncaught TypeError: dp[ds.categoryField].setFullYear is not a function at Object.AmCharts.baseYearInitialize

在 Amcharts Stock 图表中,我试图显示数据,我从数据库中以 json 形式获取这些数据。它显示的错误是“Uncaught TypeError: dp[ds.categoryField].setFullYear 不是 Object.AmCharts.baseYearInitialize 处的函数”。 JSON 数组很好,而且如果我只保留一个数据集,那么它工作正常,只要我输入一年,其数据我已经在 json 形式,它会显示错误。

var chart;
var SER = [];
//var SER;

first();

function first() {
    for (var i = 0; i < 5; i++) {
        generateChartData(2000 + i);
    }
    //SER = JSON.stringify(SER1);
    //console.log(SER1);
    dd();
}

function generateChartData(year) {
    var firstDate = new Date(year, 0, 1);
    var temp = [];
    for (var i = 0; i < 365; i++) {
        var newDate = new Date(firstDate);
        newDate.setDate(newDate.getDate() + i);
        newDate = ((newDate.getMonth() + 1) < 10 ? "0" + (newDate.getMonth() + 1) : (newDate.getMonth() + 1)) +
            "-" + (newDate.getDate() < 10 ? "0" + newDate.getDate() : newDate.getDate()) +
            "-" + year;
        temp.push({
            date: newDate,
            value: Math.round(Math.random() * (40 + i)) + 100 + i
        });
    }
    SER.push(temp);
}

function dd() {
    AmCharts.addInitHandler(function(chart) {
        AmCharts.baseYearInitialize = function(chart) {
            for (var x = 0; x < chart.dataSets.length; x++) {
                var ds = chart.dataSets[x];
                if (ds.baseYear !== undefined) {
                    for (var i = 0; i < ds.dataProvider.length; i++) {
                        var dp = ds.dataProvider[i];  dp[ds.categoryField].setFullYear(ds.baseYear);
                    }
                }
            }
        }
        AmCharts.baseYearInitialize(chart);
    }, ["stock"]);
    
    chart = AmCharts.makeChart("chartdiv", {
        "type": "stock",
        "theme": "light",
        "dataSets": [{
            "title": "2000",
            "fieldMappings": [{
                "fromField": "value",
                "toField": "value"
            }],
            "dataProvider": SER[0],
            "categoryField": "date"
        }
        /* keeping more than one dataset showing error
        , {
            "title": "2001",
            "fieldMappings": [{
                "fromField": "value",
                "toField": "value"
            }],
            "dataProvider": SER[1],
            "categoryField": "date",
            "compared": true,
            "baseYear": 2000
        }, {
            "title": "2002",
            "fieldMappings": [{
                "fromField": "value",
                "toField": "value"
            }
        */
        ],
        "panels": [{
            "title": "Value",
            "categoryAxis": {},
           "dateFormats": 'DD-MM-YYYY',
            "stockGraphs": [{
                "id": "g1",
                "valueField": "value",
                "lineThickness": 2,
                "comparable": true,
                "compareField": "value",
                "balloonText": "[[title]]:<b>[[value]]</b>",
                "compareGraphBalloonText": "[[title]]:<b>[[value]]</b>",
                "compareGraph": {
                    "dashLength": 5,
                    "lineThickness": 2
                }
            }],
            "stockLegend": {
                "periodValueTextComparing": "[[percents.value.close]]%",
                "periodValueTextRegular": "[[value.close]]"
            }
        }],
        "panelsSettings": {
            "recalculateToPercents": "never"
        },
        "chartScrollbarSettings": {
            "graph": "g1"
        },
        "chartCursorSettings": {
            "valueBalloonsEnabled": true,
            "fullWidth": true,
            "cursorAlpha": 0.1,
            "valueLineBalloonEnabled": true,
            "valueLineEnabled": true,
            "valueLineAlpha": 0.5
        },
        "periodSelector": {
            "position": "bottom",
            "periods": [{
                "period": "MM",
                "selected": true,
                "count": 1,
                "label": "1 month"
            }, {
                "period": "YYYY",
                "count": 1,
                "label": "1 year"
            }, {
                "period": "YTD",
                "label": "YTD"
            }, {
                "period": "MAX",
                "label": "MAX"
            }]
        }

    });
    $('document').ready(function() {
        $('#submit').on('click', function() {
            add(document.getElementById('year').value);
        });
    });
}

function add(yr) {
    chart.dataSets.push({
        "title": yr,
        "fieldMappings": [{
            "fromField": "value",
            "toField": "value"
        }],
        "dataProvider": SER[yr-2000],
        "categoryField": "date",
        "compared": true,
        "baseYear": 2000
    });
    AmCharts.baseYearInitialize(chart);
    chart.validateData();
}
#chartdiv {
                width: 100%;
                height: 500px;
                font-family: Verdana;
                font-size: 12px;
            }
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
        <script type="text/javascript" src="https://www.amcharts.com/lib/3/amcharts.js"></script>
        <script type="text/javascript" src="https://www.amcharts.com/lib/3/serial.js"></script>
        <script type="text/javascript" src="https://www.amcharts.com/lib/3/themes/light.js"></script>
        <script type="text/javascript" src="https://www.amcharts.com/lib/3/amstock.js"></script>
        <input type="text" id="year"><input type="submit" id="submit">
        <div id="chartdiv"></div>

我将日期格式设为 "DD-MM-YYYY"。 为什么会出现此错误?

插件假定日期已经是日期对象。由于您使用的是字符串日期,因此您需要在将日期添加到数据提供程序之前将日期转换为日期对象,或者更新插件以将字符串日期转换为日期对象。

如果您使用的是基于字符串的日期,则必须设置 dataDateFormat 以便图表知道如何正确解析您的日期。您在 generateChartData 函数中生成的 dataProvider 中的字符串日期实际上是 "MM-DD-YYYY" 格式,因此您需要在图表配置的顶层设置 dataDateFormat: "MM-DD-YYYY"

chart = AmCharts.makeChart("chartdiv", {
  // ...
  "dataDateFormat": "MM-DD-YYYY",
  // ...
}

从那里开始,您需要更新插件以检查 setFullYear 是否是该数据点的函数,并先将其转换为日期对象,然后再使用 AmCharts.stringToDate:

  AmCharts.addInitHandler(function(chart) {
    AmCharts.baseYearInitialize = function(chart) {
      for (var x = 0; x < chart.dataSets.length; x++) {
        var ds = chart.dataSets[x];
        if (ds.baseYear !== undefined) {
          for (var i = 0; i < ds.dataProvider.length; i++) {
            var dp = ds.dataProvider[i];
            // if this is not a date object (i.e. setFullYear is not defined) convert it using AmCharts.stringToDate and your chart's dataDateFormat)
            if (!dp[ds.categoryField].setFullYear) {
              dp[ds.categoryField] = AmCharts.stringToDate(dp[ds.categoryField], chart.dataDateFormat);
            }
            dp[ds.categoryField].setFullYear(ds.baseYear);
          }
        }
      }
    }
    AmCharts.baseYearInitialize(chart);
  }, ["stock"]);

我还调整了您的代码,以在将输入添加到数据提供程序之前检查输入是否为数字和有效数组元素:

var chart;
var SER = [];
//var SER;

first();

function first() {
  for (var i = 0; i < 5; i++) {
    generateChartData(2000 + i);
  }
  //SER = JSON.stringify(SER1);
  //console.log(SER1);
  dd();
}

function generateChartData(year) {
  var firstDate = new Date(year, 0, 1);
  var temp = [];
  for (var i = 0; i < 365; i++) {
    var newDate = new Date(firstDate);
    newDate.setDate(newDate.getDate() + i);
    newDate = ((newDate.getMonth() + 1) < 10 ? "0" + (newDate.getMonth() + 1) : (newDate.getMonth() + 1)) +
      "-" + (newDate.getDate() < 10 ? "0" + newDate.getDate() : newDate.getDate()) +
      "-" + year;
    temp.push({
      date: newDate,
      value: Math.round(Math.random() * (40 + i)) + 100 + i
    });
  }
  SER.push(temp);
}

function dd() {
  AmCharts.addInitHandler(function(chart) {
    AmCharts.baseYearInitialize = function(chart) {
      for (var x = 0; x < chart.dataSets.length; x++) {
        var ds = chart.dataSets[x];
        if (ds.baseYear !== undefined) {
          for (var i = 0; i < ds.dataProvider.length; i++) {
            var dp = ds.dataProvider[i];
            // if this is not a date object (i.e. setFullYear is not defined) convert it using AmCharts.stringToDate and your chart's dataDateFormat)
            if (!dp[ds.categoryField].setFullYear) {
              dp[ds.categoryField] = AmCharts.stringToDate(dp[ds.categoryField], chart.dataDateFormat);
            }
            dp[ds.categoryField].setFullYear(ds.baseYear);
          }
        }
      }
    }
    AmCharts.baseYearInitialize(chart);
  }, ["stock"]);

  chart = AmCharts.makeChart("chartdiv", {
    "type": "stock",
    "theme": "light",
    "dataDateFormat": "MM-DD-YYYY",
    "dataSets": [{
        "title": "2000",
        "fieldMappings": [{
          "fromField": "value",
          "toField": "value"
        }],
        "dataProvider": SER[0],
        "categoryField": "date"
      }
      /* keeping more than one dataset showing error
      , {
          "title": "2001",
          "fieldMappings": [{
              "fromField": "value",
              "toField": "value"
          }],
          "dataProvider": SER[1],
          "categoryField": "date",
          "compared": true,
          "baseYear": 2000
      }, {
          "title": "2002",
          "fieldMappings": [{
              "fromField": "value",
              "toField": "value"
          }
      */
    ],
    "panels": [{
      "title": "Value",
      "categoryAxis": {},
      "dateFormats": 'DD-MM-YYYY',
      "stockGraphs": [{
        "id": "g1",
        "valueField": "value",
        "lineThickness": 2,
        "comparable": true,
        "compareField": "value",
        "balloonText": "[[title]]:<b>[[value]]</b>",
        "compareGraphBalloonText": "[[title]]:<b>[[value]]</b>",
        "compareGraph": {
          "dashLength": 5,
          "lineThickness": 2
        }
      }],
      "stockLegend": {
        "periodValueTextComparing": "[[percents.value.close]]%",
        "periodValueTextRegular": "[[value.close]]"
      }
    }],
    "panelsSettings": {
      "recalculateToPercents": "never"
    },
    "chartScrollbarSettings": {
      "graph": "g1"
    },
    "chartCursorSettings": {
      "valueBalloonsEnabled": true,
      "fullWidth": true,
      "cursorAlpha": 0.1,
      "valueLineBalloonEnabled": true,
      "valueLineEnabled": true,
      "valueLineAlpha": 0.5
    },
    "periodSelector": {
      "position": "bottom",
      "periods": [{
        "period": "MM",
        "selected": true,
        "count": 1,
        "label": "1 month"
      }, {
        "period": "YYYY",
        "count": 1,
        "label": "1 year"
      }, {
        "period": "YTD",
        "label": "YTD"
      }, {
        "period": "MAX",
        "label": "MAX"
      }]
    }

  });
  $('document').ready(function() {
    $('#submit').on('click', function() {
      add(+document.getElementById('year').value);
    });
  });
}

function add(yr) {
  if (!isNaN(yr) && SER[yr - 2000] !== undefined) {
    chart.dataSets.push({
      "title": yr,
      "fieldMappings": [{
        "fromField": "value",
        "toField": "value"
      }],
      "dataProvider": SER[yr - 2000],
      "categoryField": "date",
      "compared": true,
      "baseYear": 2000
    });
    AmCharts.baseYearInitialize(chart);
    chart.validateData();
  }
}
#chartdiv {
  width: 100%;
  height: 500px;
  font-family: Verdana;
  font-size: 12px;
}
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script type="text/javascript" src="https://www.amcharts.com/lib/3/amcharts.js"></script>
<script type="text/javascript" src="https://www.amcharts.com/lib/3/serial.js"></script>
<script type="text/javascript" src="https://www.amcharts.com/lib/3/themes/light.js"></script>
<script type="text/javascript" src="https://www.amcharts.com/lib/3/amstock.js"></script>
<input type="text" id="year"><input type="submit" id="submit">
<div id="chartdiv"></div>