简体   繁体   English

点击图例,打开和关闭一系列谷歌图表

[英]toggling series of google chart on and off by clicking on legend

I have an area chart that has 6 series. 我有一个有6个系列的面积图。 I want the user to be able to click on the legend to toggle the visibility of a series. 我希望用户能够点击图例来切换系列的可见性。

I found this example & have tried including it in my code below but nothing happens. 我找到了这个例子 ,并尝试将其包含在我的代码中,但没有任何反应。 Before adding this code if I clicked on one of the series in the legend the series would become thicker, then click on it again & it would go back to normal, believe this is some default behaviour. 在添加此代码之前,如果我点击了图例中的一个系列,那么系列会变得更厚,然后再次点击它会恢复正常,相信这是一些默认行为。 However with this code included once the series gets thicker I can't do anything, ie zoom or click on the chart to get the value of a point. 然而,一旦系列变得更厚,包含此代码我就无法做任何事情,即缩放或点击图表以获得一个点的值。

Not sure what I am missing? 不确定我错过了什么?

Update 更新

I have also tried following this post but same result. 我也尝试过这篇文章,但结果相同。

latest update 最新更新

I have changed my code to the following. 我已将代码更改为以下内容。

The error I'm getting now is the following... 我现在得到的错误如下......

Uncaught Error: Invalid column index 8. Should be an integer in the range [0-7]. 未捕获的错误:列索引无效8.应该是[0-7]范围内的整数。 at gvjs_en (jsapi_compiled_default_module.js:75) at gvjs_P.gvjs_.uc (jsapi_compiled_default_module.js:92) at gvjs_P.gvjs_.Za (jsapi_compiled_default_module.js:91) at Data.displayed.reduce (jScore.js:220) at Array.reduce () at vparse (jScore.js:214) at showHideSeries (jScore.js:202) at gvjs_Zn. at gvjs_en(jsapi_compiled_default_module.js:75)at gvjs_P.gvjs_.uc(jsapi_compiled_default_module.js:92)at gvjs_P.gvjs_.Za(jsapi_compiled_default_module.js:91)at Data.displayed.reduce(jScore.js:220)at Array .duce()at vparse(jScore.js:214)at showHideSeries(jScore.js:202)at gvjs_Zn。 (jsapi_compiled_default_module.js:179) at gvjs__n (jsapi_compiled_default_module.js:129) at gvjs_Zn.gvjs_.dispatchEvent (jsapi_compiled_default_module.js:127) (jsapi_compiled_default_module.js:179)在gvjs__n(jsapi_compiled_default_module.js:129)gvjs_Zn.gvjs_.dispatchEvent(jsapi_compiled_default_module.js:127)

My HTML 我的HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script src="scripts/jScore.js"></script>

<script type="text/javascript">
    google.charts.load('current', { 'packages': ['corechart', 'table'] });
</script>

</head>
<body>
<div id="chartScore" style="height:1000px"></div>
</body>
</html>

My JS file 我的JS文件

var MyData = {};

$(document).ready(function () {

$.ajax({
    type: 'GET',
    url: 'api/Score',
    dataType: 'json',
    success: function (data) {
        MyData.dataValues = data;
        PopulateData();
        DrawChartScores();
    },
    error: function () {
        alert("Error loading data! Please try again");
    }
});

};


var Data = {};

function PopulateData() {

Data = {
    displayed: [...MyData.dataValues],
    hidden: Object.keys(MyData.dataValues[0]).reduce((a, c) => {
        a[c] = false;
        return a;
    }, {}),
    map: Object.keys(MyData.dataValues[0])
};
}

function DrawChartScores() {

 var dataValues = MyData.dataValues;
 var data = new google.visualization.DataTable();
 var options = {
    title: 'Scores', width: '80%', height: '80%',
    explorer:
        {
            keepInBounds: true,
            actions: ['dragToZoom', 'rightClickToReset']
        },
    series: Data.map.reduce((a, c, i) => {
        a[i] = {};
        return a;
    }, {})
  };

data.addColumn('date', 'Day');
data.addColumn('number', 'A');
data.addColumn('number', 'B');
data.addColumn('number', 'C');
data.addColumn('number', 'D');
data.addColumn('number', 'E');
data.addColumn('number', 'F');
data.addColumn('number', 'Nrs');

// add data
for (var i = 0; i < dataValues.length; i++) {
    data.addRow([new Date(dataValues[i].DateRet), dataValues[i].A, dataValues[i].B, dataValues[i].C,
        dataValues[i].D, dataValues[i].E, dataValues[i].F, dataValues[i].Nrs]);
}

var chart = new google.visualization.AreaChart(document.getElementById('chartScore'));
var last = {
    column: true,
    row: true
  };

 function showHideSeries() {
    var sel = chart.getSelection();

    if (sel.length === 0 && last.row === null) {
        Data.hidden[Data.map[last.column]] = !Data.hidden[Data.map[last.column]];
    } else if (sel.length && sel[0].row === null) {
        // toggle the current item selected
        Data.hidden[Data.map[sel[0].column]] = !Data.hidden[Data.map[sel[0].column]];
        last = sel[0];
    } else {
        return;
    }

    vparse(data);
    options = vkillLegend(options);
    chart.draw(data, options);

   };

google.visualization.events.addListener(chart, 'select', showHideSeries);
chart.draw(data, options);

};

function vparse(data) {
 Data.displayed.reduce((a, c, i) => {
    for (let k in c) {
        if (k === "DateRet") continue;
        if (Data.hidden[k])
            data.setValue(i, Data.map.indexOf(k), null);
        else
            data.setValue(i, Data.map.indexOf(k), c[k]);
    }
    return true;
}, []);
return data;
}

function vkillLegend(options) {
 options.series = Object.keys(options.series).reduce((a, c, i) => {
    let current = {};
    if (Data.hidden[Data.map[i]]) current.color = "#CCCCCC";
    else c.color = null;
    a[i - 1] = current;
    return a;
}, {});
return options;
};

Explanation at the bottom, here is the working code: 底部的说明,这是工作代码:

 // jshint esnext: true google.charts.load('current', {'packages': ['corechart', 'table']}); var dataValues = [{DateScore: '2018-6-14', A: 1000, B: 900, C: 800, D: 700, E: 600, F: 500, NrS: 400, }, {DateScore: '2018-6-15', A: 1000, B: 900, C: 800, D: 700, E: 600, F: 500, NrS: 400, }, {DateScore: '2018-6-17', A: 1000, B: 900, C: 800, D: 700, E: 600, F: 500, NrS: 400, }, {DateScore: '2018-6-22', A: 800, B: 600, C: 1000, D: 900, E: 300, F: 100, NrS: 600, } ]; var Data = { displayed: [...dataValues], hidden: Object.keys(dataValues[0]).reduce((a, c) => { a[c] = false; return a; }, {}), map: Object.keys(dataValues[0]) }; google.charts.setOnLoadCallback(DrawChartScores); function DrawChartScores() { var data = new google.visualization.DataTable(); var options = { title: 'Scores', width: '80%', height: '80%', explorer: { keepInBounds: true, actions: ['dragToZoom', 'rightClickToReset'] }, series: Data.map.reduce((a, c, i) => { a[i] = {}; return a; }, {}) }; data.addColumn('date', 'Day'); data.addColumn('number', 'A'); data.addColumn('number', 'B'); data.addColumn('number', 'C'); data.addColumn('number', 'D'); data.addColumn('number', 'E'); data.addColumn('number', 'F'); data.addColumn('number', 'NrS'); for (var i = 0; i < dataValues.length; i++) { let newRow = Object.values(dataValues[i]); newRow[0] = new Date(newRow[0]); data.addRow(newRow); } var chart = new google.visualization.AreaChart(document.getElementById('chartP')); var last = { column: true, row: true }; function showHideSeries() { var sel = chart.getSelection(); if (sel.length === 0 && last.row === null) { Data.hidden[Data.map[last.column]] = !Data.hidden[Data.map[last.column]]; } else if (sel.length && sel[0].row === null) { // toggle the current item selected Data.hidden[Data.map[sel[0].column]] = !Data.hidden[Data.map[sel[0].column]]; last = sel[0]; } else { return; } vparse(data); options = vkillLegend(options); chart.draw(data, options); } google.visualization.events.addListener(chart, 'select', showHideSeries); chart.draw(data, options); } function vparse(data) { Data.displayed.reduce((a, c, i) => { for (let k in c) { if (k === "DateScore") continue; if (Data.hidden[k]) data.setValue(i, Data.map.indexOf(k), null); else data.setValue(i, Data.map.indexOf(k), c[k]); } return true; }, []); return data; } function vkillLegend(options) { options.series = Object.keys(options.series).reduce((a, c, i) => { let current = {}; if (Data.hidden[Data.map[i]]) current.color = "#CCCCCC"; else c.color = null; a[i - 1] = current; return a; }, {}); return options; } 
 <!DOCTYPE html> <html> <head> <title>My Title</title> <meta charset="utf-8" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script> </head> <body> <div id="chartP" style="height:1000px"></div> </body> 

Explanation 说明

Variables 变量

  • Data object: Data对象:
    • displayed - array that contains all the starting data provided by dataValues displayed - 包含dataValues提供的所有起始数据的dataValues
    • hidden - keeps track of the legend items that have been hidden with a simple object mapping the column key to the boolean representation of their display hidden - 使用将列键映射到其显示的布尔表示的简单对象来跟踪已隐藏的图例项
    • map - simply an array where the index of the item is the location on the chart, also used to convert column index to column key map - 只是一个数组,其中项的索引是图表上的位置,也用于将列索引转换为列键
  • options.series - an object representation of each of the columns; options.series - 每个列的对象表示; this is used to modify the legend color when clicked. 这用于在单击时修改图例颜色。
  • last - this is more-so a product of google charts event handling; last - 这是谷歌图表事件处理的产物; essentially, if you click on the same thing twice, the second click will register with no data from getSelection() . 实质上,如果你点击相同的东西两次,第二次点击将注册没有来自getSelection()数据。 This means we have to store all the previous clicks if we want a user-friendly experience. 这意味着如果我们想要用户友好的体验,我们必须存储所有之前的点击。 Otherwise, the user would have to click somewhere else on the chart before clicking back on the legend item. 否则,用户必须先单击图表上的其他位置,然后再单击图例项。

Functions 职能

When the legend item is clicked, there are a few things that happens: 单击图例项时,会发生以下几种情况:

  1. showHideSeries() decides whether or not the click was on the legend, and if it was on the legend, act accordingly - regardless of the selection being empty or not; showHideSeries()决定点击是否在图例上,如果它在图例上,则相应地采取行动 - 无论选择是否为空;
  2. vparse() prepares the new data set based on the base data provided in dataValues vparse()根据dataValues提供的基础数据准备新数据集
  3. vkillLegend() kills the styling on the legend items which are no longer present in the data set, and restores styling for data that was re-added; vkillLegend()杀死数据集中不再存在的图例项的样式,并恢复重新添加的数据的样式;
  4. Finally, we are ready to push all the changes to the chart, and we can do that by using chart.draw() 最后,我们准备将所有更改推送到图表,我们可以通过使用chart.draw()

You can see a working example by clicking the Run code snippet button above. 您可以点击上面的Run code snippet按钮查看工作示例。

I hope this helps! 我希望这有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM