Hiding columns with Amcharts possible via legend?

2019-08-20 10:09发布

问题:

I'm currently working on a graph to display some data I have, I have a legend set up that makes it possible to show/not show certain values in the graph. However, I was wondering if the same method can be applied to the columns of a graph. With the code below;

<html>
<body>
<!-- Styles -->
<style>
#chartdiv {
    width       : 100%;
    height      : 500px;
    font-size   : 11px;
}                       
</style>
<!-- Resources -->
<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/plugins/export/export.min.js"></script>
<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/themes/light.js"></script>
<!-- Chart code -->
<script>
var chart = AmCharts.makeChart("chartdiv", {
    "type": "serial",
     "theme": "light",
    "categoryField": "year",
    "rotate": false,
    "legend": {
        "useGraphSettings": true
    },
    "startDuration": 1,
    "categoryAxis": {
        "gridPosition": "start",
        "position": "left"
    },
    "trendLines": [],
    "graphs": [
        {
            "balloonText": "Income:[[value]]",
            "fillAlphas": 0.8,
            "id": "AmGraph-1",
            "lineAlpha": 0.2,
            "title": "Income",
            "type": "column",
            "valueField": "income"
        },
        {
            "balloonText": "Expenses:[[value]]",
            "fillAlphas": 0.8,
            "id": "AmGraph-2",
            "lineAlpha": 0.2,
            "title": "Expenses",
            "type": "column",
            "valueField": "expenses"
        }
    ],
    "guides": [],
    "valueAxes": [
        {
            "id": "ValueAxis-1",
            "position": "top",
            "axisAlpha": 0
        }
    ],
    "allLabels": [],
    "balloon": {},
    "titles": [],
    "dataProvider": [
        {
            "year": 2005,
            "income": 23.5,
            "expenses": 18.1
        },
        {
            "year": 2006,
            "income": 26.2,
            "expenses": 22.8
        },
        {
            "year": 2007,
            "income": 30.1,
            "expenses": 23.9
        },
        {
            "year": 2008,
            "income": 29.5,
            "expenses": 25.1
        },
        {
            "year": 2009,
            "income": 24.6,
            "expenses": 25
        }
    ],
    "export": {
        "enabled": true
     }

});
</script>
<!-- HTML -->
<div id="chartdiv"></div>                               
</body>
</html>

(based on the clustered bar graph example) it's possible to (de)select income or expenses, but would it also be able to have a legend to (de)select the separate years? E.g. completely hiding 2006 while showing the other years or only showing 2005 and 2009.?

I have looked around and have found some discussions resembling the problem that I have, but they don't exactly match what I'm looking for.

Any thoughts?

回答1:

This cannot be done using amCharts' legend. Instead, you should change your dataProvider and refresh your chart.

Example, if you wanted to hide 2007 from your chart:

HTML

<button type="button" onclick="hideYear(2007)">hide 2007</button>

JS

var my_data = [
    {
        "year": 2005,
        "income": 23.5,
        "expenses": 18.1
    },
    {
        "year": 2006,
        "income": 26.2,
        "expenses": 22.8
    },
    {
        "year": 2007,
        "income": 30.1,
        "expenses": 23.9
    },
    {
        // ...
    }
];

// create your chart initially using all data
var chart = AmCharts.makeChart("chartdiv", {
  "type": "serial",
  "dataProvider": my_data,
  // ...
});

function hideYear(year){

  var new_dataprovider = [];

  // loop over my_data
  my_data.forEach(function(item){
    if(item.year != year){
      new_dataprovider.push(item);
    }
  });

  // now that we have our new dataprovider
  // excluding a certain year,
  // update our chart
  chart.dataProvider = new_dataprovider;

  // validateData will refresh the chart
  chart.validateData();

}

Depending on your chart config, this will hide the year 2007 completely (from the category axis). Instead of leaving out the data item, you might want to set the "income" and "expenses" fields to null, so that the year (category) itself will remain visible.

Hope that makes sense.



回答2:

Thanks to @Robbert for providing the code of how to hide a column. I worked it out further and now you're able to hide multiple columns at once and also show them again with a selection menu and two buttons. The full code is below or can be found in a working example here.

<html>
<body>
<style>
#chartdiv {
    width       : 100%;
    height      : 500px;
    font-size   : 11px;
}                       
</style>
<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/plugins/export/export.min.js"></script>
<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/themes/light.js"></script>
<script>
var my_data = [
    {
        "year": 2005,
        "income": 23.5,
        "expenses": 18.1
    },
    {
        "year": 2006,
        "income": 26.2,
        "expenses": 22.8
    },
    {
        "year": 2007,
        "income": 30.1,
        "expenses": 23.9
    },
    {
        "year": 2008,
        "income": 26.1,
        "expenses": 24.4
    },
    {
        "year": 2009,
        "income": 24.1,
        "expenses": 23.7
    }
];

var chart = AmCharts.makeChart("chartdiv", {
    "type": "serial",
     "theme": "light",
    "categoryField": "year",
    "rotate": false,
    "legend": {
        "useGraphSettings": true
    },
    "startDuration": 1,
    "categoryAxis": {
        "gridPosition": "start",
        "position": "left"
    },
    "trendLines": [],
    "graphs": [
        {
            "balloonText": "Income:[[value]]",
            "fillAlphas": 0.8,
            "id": "AmGraph-1",
            "lineAlpha": 0.2,
            "title": "Income",
            "type": "column",
            "valueField": "income"
        },
        {
            "balloonText": "Expenses:[[value]]",
            "fillAlphas": 0.8,
            "id": "AmGraph-2",
            "lineAlpha": 0.2,
            "title": "Expenses",
            "type": "column",
            "valueField": "expenses"
        }
    ],
    "guides": [],
    "valueAxes": [
        {
            "id": "ValueAxis-1",
            "position": "top",
            "axisAlpha": 0
        }
    ],
    "allLabels": [],
    "balloon": {},
    "titles": [],
    "dataProvider": my_data,
    "export": {
        "enabled": true
     }
});
var hiddenYears = [];
function hideYear(){
    var selection = document.getElementById("yearSelection");
    var selectedYear = Number(selection.options[selection.selectedIndex].value);
    hiddenYears.push(selectedYear);

    var new_dataprovider = [];

    // loop over my_data
    my_data.forEach(function(item){
        if(!hiddenYears.includes(item.year)){
            new_dataprovider.push(item);
        }
    });

    // now that we have our new dataprovider
    // excluding a certain year,
    // update our chart
    chart.dataProvider = new_dataprovider;

    // validateData will refresh the chart
    chart.validateData();
}
function showYear(){
    var selection = document.getElementById("yearSelection");
    var selectedYear = Number(selection.options[selection.selectedIndex].value);
    var index = hiddenYears.indexOf(selectedYear);
    if (index > -1) {
        hiddenYears.splice(index, 1);
    }
    var new_dataprovider = [];
    my_data.forEach(function(item){
        if(!hiddenYears.includes(item.year)){
            new_dataprovider.push(item);
        }
    });
    // now that we have our new dataprovider
    // excluding a certain year,
    // update our chart
    chart.dataProvider = new_dataprovider;
    // validateData will refresh the chart
    chart.validateData();
}
</script>
<div id="chartdiv"></div>       
<select id="yearSelection">
    <option>Select a year</option>
</select>
<script>
var select = document.getElementById("yearSelection");
var options = [2005, 2006, 2007, 2008, 2009];
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>
<button type="button" onclick="hideYear(document.getElementById('yearSelection'))">Hide</button>
<button type="button" onclick="showYear(document.getElementById('yearSelection'))">Show</button>
</body>
</html>