我正在尝试使用谷歌图表创建一些数据的散点图可视化。最初,我希望在用户单击按钮之前呈现图表但是为空。我希望它被绘制为空的原因是,即使没有加载数据,图表也会占据页面上的正确区域。
按html按钮会向远程服务器发送请求,获取一些数据,然后在加载数据后刷新显示,以显示可爱的更新图形。
问题是,即使将数据添加到TableData变量并请求dashboard.draw(),图表显示也不会更新。我觉得我必须在这里遗漏一些明显的东西,因为关于堆栈溢出的所有建议都表明只需将数据添加到DataTable并调用draw()就应该更新表。表DOES的控制器似乎更新以反映新数据,但图表本身不会。
如果我在调用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()
我已经包含了最低工作示例at jsfiddle here。任何人都可以找出图表无法正确更新的原因吗?
感谢。
答案 0 :(得分:0)
不确定原因,但是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))})
答案 1 :(得分:0)
显然,一旦最初使用dashboard.draw(数据)绘制了空图形,随后应该在图形(ChartWrapper)本身上执行更新。因此,不应调用dashboard.draw(data),而应直接调用dashboardChart.draw()。这样做无需手动更改日期范围滑块。这种行为有点奇怪,在文档中并不明显。
文档here的第8部分:
- 绘制后的程序化更改
醇>如果您需要以编程方式更改仪表板状态,则可以执行此操作 所以直接在ControlWrapper和ChartWrapper上操作 属于它的实例。经验法则是执行任何操作 直接在特定的ControlWrapper(或 ChartWrapper)实例:例如,更改控件选项或状态 分别通过setOption()和setState()调用它的draw() 之后的方法。然后仪表板将更新以匹配 要求更改。