【问题标题】:toggling series of google chart on and off by clicking on legend通过单击图例打开和关闭一系列谷歌图表
【发布时间】:2018-06-12 08:50:02
【问题描述】:

我有一个有 6 个系列的面积图。我希望用户能够单击图例来切换系列的可见性。

我找到了this example 并尝试将其包含在我的代码中,但没有任何反应。在添加此代码之前,如果我单击图例中的一个系列,该系列会变厚,然后再次单击它会恢复正常,相信这是一些默认行为。但是,一旦系列变得更厚,包含此代码后,我将无能为力,即缩放或单击图表以获取点的值。

不确定我错过了什么?

更新

我也尝试过关注这个post,但结果相同。

最新更新

我已将代码更改为以下内容。

我现在遇到的错误如下...

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

我的 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>

我的 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;
};

【问题讨论】:

    标签: javascript jquery google-api google-visualization


    【解决方案1】:

    底部的解释,这里是工作代码:

    // 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>

    说明

    变量

    • Data 对象:
      • displayed - 包含dataValues 提供的所有起始数据的数组
      • hidden - 使用一个简单的对象来跟踪隐藏的图例项,将列键映射到其显示的布尔表示
      • map - 只是一个数组,其中项目的索引是图表上的位置,也用于将列索引转换为列键
    • options.series - 每一列的对象表示;这用于在单击时修改图例颜色。
    • last - 这更像是谷歌图表事件处理的产物;本质上,如果您两次单击同一事物,则第二次单击将注册而没有来自getSelection() 的数据。这意味着如果我们想要用户友好的体验,我们必须存储所有以前的点击。否则,用户必须先单击图表上的其他位置,然后再单击图例项。

    功能

    当点击图例项时,会发生一些事情:

    1. showHideSeries() 决定点击是否在图例上,如果在图例上,则采取相应的行动——无论选择是否为空;
    2. vparse()根据dataValues提供的基础数据准备新的数据集
    3. vkillLegend() 取消数据集中不再存在的图例项的样式,并恢复重新添加的数据的样式;
    4. 最后,我们准备好将所有更改推送到图表中,我们可以使用chart.draw()

    您可以通过点击上面的 Run code snippet 按钮查看一个工作示例。

    我希望这会有所帮助!

    【讨论】:

    • 感谢您的精彩回答。我已经在我的帖子中更新了我的代码,但仍然有问题,这更多是由于我缺乏知识和第一次这样做而不是你的解释。我不确定我是否在示例中正确使用了 var Data = {displayed...?
    • 抱歉没有保存我的更改,但现在有
    • var Data 在哪里填充?我认为我不应该在 $(document).ready 函数中使用它?但如果它不在这里,我不确定它是如何填充的?
    • 您可能应该在 ajax 回调中重新填充它
    • 谢谢实际上只是这样做了。得到一个无效的列索引错误,所以认为我越来越近了
    猜你喜欢
    • 1970-01-01
    • 2020-04-28
    • 2014-11-18
    • 2012-04-18
    • 1970-01-01
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多