AmCharts 从 dataProvider 中删除列,validateData() 不起作用

AmCharts removing columns from dataProvider with validateData() not working

我最近询问了一个使用 hide/show 按钮的 ,它运行良好。但是,我现在将函数分离到不同的文件中以创建一个更加动态的 Web 应用程序。

页面 peptide.html 主要包含 HTML 代码,参考 displayAmCharts.js显示 AmChart 和任何文件,在本例中为 1A80_HUMAN_R_QDAYDGK_D.js,在 data/peptide 文件夹中动态加载数据。在 AmChart 中加载和显示数据工作正常,但是在尝试实现 hide/show 函数时我遇到了 AmChart 错误。

每次调用函数 hideValue() 时,都会生成一个新的 dataProvider 并替换旧的 AmChart 中的结果只是 BLANK。在这个 JS Bin example 中自己尝试,显示一些数据,select 隐藏一列,单击隐藏,您会看到图表的轮廓几乎保持不变,图例仍然显示相同 selection 但显示的是实际数据。

奇怪的是 displayAmCharts() 中的注释代码可以替换值,但是当这些不是硬编码时,替换不起作用。一些控制 additionalData 包含的内容的日志没有显示任何异常,即与默认 dataProvider 中的数据结构相同。

关于为什么数据未正确显示的任何线索?

以下代码也可以在JS Bin上找到:

<html>
  <head>
    <link rel="stylesheet" href="https://www.amcharts.com/lib/3/plugins/export/export.css" type="text/css" media="all" />
    <script src="https://www.amcharts.com/lib/3/amcharts.js"></script>
    <script src="https://www.amcharts.com/lib/3/plugins/export/export.min.js"></script>
    <script src="https://www.amcharts.com/lib/3/serial.js"></script>
    <script src="https://www.amcharts.com/lib/3/themes/light.js"></script>
  </head>   
<script>
  // Source would be C:/Users/Username/Documents/Visualisation Tool/data/peptide/1A80_HUMAN_R_QDAYDGK_D.js
  var graphValues = [{
    "balloonText": "Control: [[value]]",
    "fillAlphas": 1,
    "id": "Control",
    "lineAlpha": 1,
    "lineColor": "#008000",
    "title": "Control",
    "type": "column",
    "newStack": true,
    "valueField": "Control",
    "hidden": true},
{
    "balloonText": "Control SD: [[value]]",
    "fillAlphas": 1,
    "id": "Control SD",
    "lineAlpha": 1,
    "lineColor": "#000000",
    "title": "Control SD",
    "type": "column",
    "valueField": "Control SD",
    "hidden": true},
{
    "balloonText": "Sample A: [[value]]",
    "fillAlphas": 1,
    "id": "Sample A",
    "lineAlpha": 1,
    "lineColor": "#008080",
    "title": "Sample A",
    "type": "column",
    "newStack": true,
    "valueField": "Sample A",
    "hidden": true},
{
    "balloonText": "Sample A SD: [[value]]",
    "fillAlphas": 1,
    "id": "Sample A SD",
    "lineAlpha": 1,
    "lineColor": "#000000",
    "title": "Sample A SD",
    "type": "column",
    "valueField": "Sample A SD",
    "hidden": true},
{
    "title": "All",
    "id": "all",
    "legendValueText": "",
    "legendPeriodValueText": "",
    "hidden": true
}];
var dataValues = [{
    "glycan": "Hex5HexNAc4NeuAc1",
    "Control": 100.0,
    "Control SD": 10.0,
    "Sample A": 80.0,
    "Sample A SD": 8.0},
    {
    "glycan": "Hex5HexNAc4NeuAc2",
    "Control": 50.0,
    "Control SD": 10.0,
    "Sample A": 4.0,
    "Sample A SD": 4.0}
    ];
</script>
  <script>
    // Source would be C:/Users/Username/Documents/Visualisation Tool/scripts/displayAmCharts.js
    var hiddenValues = [];
    var dataProviderVals;

    function displayAmCharts(additionalData){
      var graphsVals = graphValues;
      dataProviderVals = dataValues;
      var chart = AmCharts.makeChart("chartdiv", {
        "type": "serial",
        "dataProvider": dataProviderVals,
        "legend": {
          "useGraphSettings": true,
          "borderAlpha": 1,
          "align": "center",
          "spacing":  125,
          "listeners": [ {
            "event": "hideItem",
            "method": legendHandler
          }, {
            "event": "showItem",
            "method": legendHandler
          }]
        },
        "categoryField": "glycan",
        "categoryAxis": {
          "autoWrap": true
        },
        "rotate": false,
        "graphs": graphsVals,
        "valueAxes": [
          {
            "stackType": "regular",
            "id": "ValueAxis-1",
            "position": "left",
            "axisAlpha": 1
          }
        ],
        "export": {
          "enabled": true
        }
      });   

      /*
      This manual code below works to replace the data.

      var test = [{
        "glycan": "Hex5HexNAc4NeuAc3",
        "Control": 100.0,
        "Control SD": 10.0,
        "Sample A": 80.0,
        "Sample A SD": 8.0},
        {
        "glycan": "Hex5HexNAc4NeuAc4",
        "Control": 50.0,
        "Control SD": 10.0,
        "Sample A": 4.0,
        "Sample A SD": 4.0}
        ];
      chart.dataProvider = test;
      chart.validateData();
      */

      if(additionalData != undefined){
        // Replace the dataProvider with additionalData from hideValue and redraw the chart.
        chart.dataProvider = additionalData;
        chart.validateData();
      }
      function legendHandler(evt) {
        var state = evt.dataItem.hidden;
        if (evt.dataItem.id == "all") {
          for (var i1 in evt.chart.graphs) {
            if (evt.chart.graphs[ i1 ].id != "all") {
              evt.chart[evt.dataItem.hidden ? "hideGraph" : "showGraph" ]( evt.chart.graphs[ i1 ]);
            }
          }
        }
      }
    }
    function hideValue(){
      var selection = document.getElementById("selection");
      var selectedValue = selection.options[selection.selectedIndex].value;
      hiddenValues.push(selectedValue);
      var newDataProvider = [];
      dataValues.forEach(function(item){
        if(hiddenValues.includes(item.glycan) == false){
          newDataProvider.push(item);
        }
      });
      displayAmCharts(newDataProvider);
    }

    function fillSelection(){
      var select = document.getElementById("selection");
      var options = [];
      dataProviderVals.forEach(function(item){
        options.push(item.glycan);
      });
      for(var i = 0; i < options.length; i++) {
        var opt = options[i];
        var el = document.createElement("option");
        el.textContent = opt;
        el.value = opt;
        select.appendChild(el);
      } 
    }
  </script>

    <body onload="displayAmCharts(); fillSelection()">
        <header>
            <h1><b>Visualisation Tool<b></h1>
        </header>
        <h2></h2>
        <div id="chartdiv"><p>Unfortunately there is no data available.</p></div>

        <div>
            <select class="select" id="selection">
                <option disabled selected>Select an option.</option>
            </select>
            <button class="button" type="button" onclick="hideValue()">Hide</button>
            <button class="button" type="button">Show</button>
        </div>
    </body>
    <script type="text/javascript">
        // Commentary in this version as all JS scripts are included in the same page.
        // Open .JS file that contains data at C > Users > User > Documents > Tool folder > Data > Peptide > peptide based on value stored in localStorage, example would be localStorage.getItem("peptideSelection") = "1A80_HUMAN_R_QDAYDGK_D".
        // var peptide = localStorage.getItem("peptideSelection");
        // var JSLink = "C://Users//Z678187//Documents//StackExample//data//peptide//"+peptide+".js";
        // C://Users/Z678187//Documents/StackExample//data//peptide//1A80_HUMAN_R_QDAYDGK_D.js would be the file location.
        // var JSElement = document.createElement('script');
        // JSElement.src = JSLink;
        // JSElement.onload = OnceLoaded;
        // document.getElementsByTagName('head')[0].appendChild(JSElement);
        // function OnceLoaded() {
        //  displayAmCharts();
        //  fillSelection();
        // }
    </script>
</html>    

这可能与每次调用 displayAmCharts 时重新创建图表有关。这是不必要的,会使 amCharts 混淆。我会将 chart 定义为全局变量,并且只创建一次图表。

你的全局变量

var hiddenValues = [];
var dataProviderVals;
var chart = null; // chart as global variable

displayAmCharts 函数

function displayAmCharts(additionalData){

  var graphsVals = graphValues;
  dataProviderVals = dataValues;

  // create chart only once
  if(chart == null){

    chart = AmCharts.makeChart("chartdiv", {
      "type": "serial",
      "dataProvider": dataProviderVals,
      // ...
    });

  }

  if(additionalData != undefined){
    // Replace the dataProvider with additionalData from hideValue and redraw the chart.
    chart.dataProvider = additionalData;
    chart.validateData();
  }

  // ...

}

这应该可以解决问题:-)