显示空白图表,然后使用按钮更新(谷歌图表)

Showing Blank Chart then Updating It Using Button (Google Charts)

本文关键字:更新 谷歌 按钮 空白 然后 显示      更新时间:2023-09-26

我正在尝试使用谷歌图表创建一些数据的散点图可视化。最初,我希望图表是呈现的,但在用户单击按钮之前是空的。我希望它被绘制为空的原因是,即使没有加载任何数据,图表也会占据页面上正确的区域。

按下html按钮将向远程服务器发送请求,获取一些数据,然后在数据加载后刷新显示,以显示可爱的更新图形。

问题是,即使在将数据添加到TableData变量并请求dashboard.draw()之后,图形显示也不会更新。我觉得这里一定遗漏了一些明显的东西,因为所有关于堆栈溢出的建议都表明,只需将数据添加到DataTable并调用draw()就可以更新表。表的控制器似乎确实更新以反映新数据,但图表本身没有。

如果我在调用drawChart()函数时立即加载数据,那么图形就会完美地显示出来。类似地,如果我不显示一个空图表,而是在数据加载回调函数中加载数据后才调用draw(),那么图表就会正确显示。然而,当一张图表突然出现在页面上时,这看起来并不好。

HTML:

<body>
<h1>A nice chart showing user data.</h1>
<p>Simply insert a username into the text box and click get user data.</p>
<div class="usernameInputDiv">
    <form id="usernameForm1">
        Username: <input id="usernameTextBox" type="text" name="username">
    </form>
    <div class="button">
        <button class="btn">Get User Data</button>
    </div>
</div>
<div id="dashboard_div" style="width: 600px; height: 350px;">
    <div id="dashboardChart_div" style="width: 600px; height: 300px;">
    </div>
    <div id="rangeSlider_div" style="width: 600px; height: 50px;">
    </div>
 </div>
</body>

和javascript代码:

$(document).ready(function () {
    google.load("visualization", "1", {packages:["corechart", "controls"], "callback" : drawChart});
});

//Draws a scatter chart
function drawChart() {
    //Column names for adding data
    var columnNames = ["time","bytesInAvg","bytesOutAvg","bytesInMax","bytesOutMax"];
    //initialise a data structure to store the data
    var data = new google.visualization.DataTable();
    data.addColumn('datetime', 'Date');
    data.addColumn('number', 'bytesInAvg');
    data.addColumn('number', 'bytesOutAvg');
    data.addColumn('number', 'bytesInMax');
    data.addColumn('number', 'bytesOutMax');
    //Create a dashboard
    //Dashboards are used to group one (or more) graphs along with the controls for that graph
    var dashboard = new google.visualization.Dashboard(document.getElementById('dashboard_div'));
    var options = {
        title: 'Data Sent/Received Per Minute (bytes)',
        hAxis: {title: 'Time'},
        vAxis: {title: 'Data Sent/Received (bytes)'},
        legend: '' //sets the legend to be displayed, use None for no legend
    };
    //Create chart for dashboard
    var dashboardChart = new google.visualization.ChartWrapper({
        'chartType': 'ScatterChart',
        'containerId': 'dashboardChart_div',
        'options': options
    });
    //Create controller for chart
    var dateRangeSlider = new google.visualization.ControlWrapper({
        'controlType': 'ChartRangeFilter',
        'containerId': 'rangeSlider_div',
        'options': {
          'filterColumnLabel': 'Date'
        }
    });
    //bind the chart and controller together in the dashboard
    dashboard.bind(dateRangeSlider, dashboardChart);
    //No data is loaded, so just show a blank chart for now so that it occupies the space
    //and is obvious to the user.
    updateDisplay(data,dashboard);
    //This is used to get and load data from a remote service
    $('.btn').click(function() {
        console.log("Received button press event");
        getTestData(data, dashboard, columnNames);
    });
    function updateDisplay(data, dashboard){
        //get the range of the data (just use col 1 for now)
        var yRange = data.getColumnRange(1);
        var xRange = data.getColumnRange(0);
        //Update chart axes. I would like this to be done automatically,
        //but it isn't, so for now I do it by hand.
        dashboardChart.setOption('vAxis.maxValue', yRange.max);
        dashboardChart.setOption('vAxis.minValue', yRange.min);
        dashboardChart.setOption('hAxis.maxValue', xRange.max);
        dashboardChart.setOption('hAxis.minValue', xRange.min);
        //update the display
        dashboard.draw(data);
    }
    //Test function simulating querying a server (using setTimeout to simulate delay)
    //and loading the data into a DataTable
    function getTestData(data, dashboard, columnNames){
        setTimeout(function() {
            var jsonObject = [
            {time:"2014-09-25T01:17:00.000Z", "bytesInAvg":713, "bytesOutAvg":1751, "bytesInMax":6916, "bytesOutMax":18947},
            {time:"2014-09-25T01:18:00.000Z", "bytesInAvg":146, "bytesOutAvg":328, "bytesInMax":810, "bytesOutMax":2877},
            {time:"2014-09-25T01:19:00.000Z", "bytesInAvg":44, "bytesOutAvg":73, "bytesInMax":122, "bytesOutMax":196},
            {"time":"2014-09-25T01:20:00.000Z", "bytesInAvg":41, "bytesOutAvg":69, "bytesInMax":122, "bytesOutMax":196},
        ];
        addResultToDataTable(data,jsonObject,columnNames);
        updateDisplay(data, dashboard);
        }, 2000);
    }//getTestData
    function addResultToDataTable(data, result, columnNames)
    {
      for ( var i = 0; i < result.length; i++)
      {
          data.addRow([ new Date(result[i]['time']), result[i][columnNames[1]], result[i][columnNames[2]], result[i][columnNames[3]], result[i][columnNames[4]] ]);
      }
    }//addResultsToDataTable
}//drawChart()

我在这里包含了一个jsfiddle的最低限度的工作示例。有人能弄清楚为什么图表没有正确更新吗?

谢谢。

不确定原因,但您的dateRangeControl出现了问题,因此即使数据在那里,它也会按范围过滤而不显示。您可以使用进行检查

dashboard.draw(data);
console.log(dateRangeSlider.getState()) // after update, shows same date for start and end(year 1969)

因此,一个快速的解决方案是为您的数据设置一个有效的范围:

dashboard.draw(data);
dateRangeSlider.setState({end:new Date(), start:new Date(new Date().setMonth(new Date().getMonth()-1))})

全小提琴:http://jsfiddle.net/uf5wocx9/17/

显然,一旦最初使用dashboard.draw(data)绘制了空图,就应该随后对图(ChartWrapper)本身进行更新。因此,与其调用dashboard.draw(data),不如直接调用dashbardChart.draw。这样做就不需要手动更改日期范围滑块。这种行为有点奇怪,在文档中并不明显。

来自此处文档的第8节:

  1. 绘制后的程序更改

如果您需要以编程方式更改仪表板状态,您可以因此,通过直接在ControlWrapper和ChartWrapper上操作实例。经验法则是执行直接在特定ControlWrapper上需要的更改(或ChartWrapper)实例:例如,更改控件选项或状态分别通过setOption()和setState(),并调用其draw()方法。然后,仪表板将更新以匹配请求的更改。