我有两个折线图,每个都有一个rangeFilter
(就像这里的那个。)
我想同步两个图表的比例。也就是说,当一个图表更改范围视图时,它将更改vAxis max value
以适应该范围内的最大数据,并且我希望另一个图表将比例更改为相同的值。
我怎样才能实时vAxis.viewWindow.max
获得?
我有两个折线图,每个都有一个rangeFilter
(就像这里的那个。)
我想同步两个图表的比例。也就是说,当一个图表更改范围视图时,它将更改vAxis max value
以适应该范围内的最大数据,并且我希望另一个图表将比例更改为相同的值。
我怎样才能实时vAxis.viewWindow.max
获得?
如果您只是询问如何确定vAxis.viewWindow.min
(and .max
) 值,您可以使用以下代码来完成:
alert('Min ViewWindow: ' + chart.getOption('vAxis.viewWindow.min') + ', Max: ' + chart.getOption('vAxis.viewWindow.max'));
(给定一个名为 的图表包装对象chart
)。
每次调整图表时,您都可以通过向控件包装器添加 statechange 事件,让它告诉您最大/最小值:
google.visualization.events.addListener(control, 'statechange', function(e) {
if(e.inProgress == false) {
alert('Min ViewWindow: ' + chart.getOption('vAxis.viewWindow.min') + ', Max: ' + chart.getOption('vAxis.viewWindow.max'));
}
请注意,这实际上不会改变任何事情,它只会报告您想要的内容。另一方面,如果您希望图表根据图表中的过滤值更改最大/最小 viewWindow 值,那么这是我非常糟糕的实现:
function drawVisualization() {
var dashboard = new google.visualization.Dashboard(
document.getElementById('dashboard'));
var control = new google.visualization.ControlWrapper({
'controlType': 'ChartRangeFilter',
'containerId': 'control',
'options': {
// Filter by the date axis.
'filterColumnIndex': 0,
'ui': {
'chartType': 'LineChart',
'chartOptions': {
'chartArea': {'width': '90%'},
'hAxis': {'baselineColor': 'none'}
},
// Display a single series that shows the closing value of the stock.
// Thus, this view has two columns: the date (axis) and the stock value (line series).
'chartView': {
'columns': [0, 3]
},
// 1 day in milliseconds = 24 * 60 * 60 * 1000 = 86,400,000
'minRangeSize': 86400000
}
},
// Initial range: 2012-02-09 to 2012-03-20.
'state': {'range': {'start': new Date(2012, 1, 9), 'end': new Date(2012, 2, 20)}}
});
var chart = new google.visualization.ChartWrapper({
'chartType': 'CandlestickChart',
'containerId': 'chart',
'options': {
// Use the same chart area width as the control for axis alignment.
'chartArea': {'height': '80%', 'width': '90%'},
'hAxis': {'slantedText': false},
'vAxis': {'viewWindow': {'min': 0, 'max': 2000}},
'legend': {'position': 'none'}
},
// Convert the first column from 'date' to 'string'.
'view': {
'columns': [
{
'calc': function(dataTable, rowIndex) {
return dataTable.getFormattedValue(rowIndex, 0);
},
'type': 'string'
}, 1, 2, 3, 4]
}
});
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Stock low');
data.addColumn('number', 'Stock open');
data.addColumn('number', 'Stock close');
data.addColumn('number', 'Stock high');
// Create random stock values, just like it works in reality.
var open, close = 300;
var low, high;
for (var day = 1; day < 121; ++day) {
var change = (Math.sin(day / 2.5 + Math.PI) + Math.sin(day / 3) - Math.cos(day * 0.7)) * 150;
change = change >= 0 ? change + 10 : change - 10;
open = close;
close = Math.max(50, open + change);
low = Math.min(open, close) - (Math.cos(day * 1.7) + 1) * 15;
low = Math.max(0, low);
high = Math.max(open, close) + (Math.cos(day * 1.3) + 1) * 15;
var date = new Date(2012, 0 ,day);
data.addRow([date, Math.round(low), Math.round(open), Math.round(close), Math.round(high)]);
}
// This function determines the maximum and minimum values of the data
function calculateMinMax(data) {
// Get max and min values for the data table
var totalMin = data.getValue(0,1);
var totalMax = data.getValue(0,1);
for (var i = 1;i < data.getNumberOfColumns();i++) {
for (var j = 0;j < data.getNumberOfRows();j++){
if ( data.getValue(j, i) < totalMin ) {
totalMin = data.getValue(j, i);
}
if ( data.getValue(j, i) > totalMax ) {
totalMax = data.getValue(j, i);
}
}
}
// Calculate grid line axes and min/max settings
// Figure out the largest number (positive or negative)
var biggestNumber = Math.max(Math.abs(totalMax),Math.abs(totalMin));
// Round to an exponent of 10 appropriate for the biggest number
var roundingExp = Math.floor(Math.log(biggestNumber) / Math.LN10);
var roundingDec = Math.pow(10,roundingExp);
// Round your max and min to the nearest exponent of 10
var newMax = Math.ceil(totalMax/roundingDec)*roundingDec;
var newMin = Math.floor(totalMin/roundingDec)*roundingDec;
// Determine the range of your values
var range = newMax - newMin;
// Define the number of gridlines (default 5)
var gridlines = 5;
// Determine an appropriate gap between gridlines
var interval = range / (gridlines - 1);
// Round that interval up to the exponent of 10
var newInterval = Math.ceil(interval/roundingDec)*roundingDec;
// Re-round your max and min to the new interval
var finalMax = Math.ceil(totalMax/newInterval)*newInterval;
var finalMin = Math.floor(totalMin/newInterval)*newInterval;
var result = [finalMin, finalMax];
return result;
}
var axisMinMax = calculateMinMax(data);
alert('Min: ' + axisMinMax[0] + ', Max: ' + axisMinMax[1]);
chart.setOption('vAxis.viewWindow.min', axisMinMax[0]);
chart.setOption('vAxis.viewWindow.max', axisMinMax[1]);
dashboard.bind(control, chart);
dashboard.draw(data);
google.visualization.events.addListener(control, 'statechange', function(e) {
if(e.inProgress == false) {
var axisMinMax = calculateMinMax(chart.getDataTable());
chart.setOption('vAxis.viewWindow.min', axisMinMax[0]);
chart.setOption('vAxis.viewWindow.max', axisMinMax[1]);
var filteredData = chart.getDataTable();
chart.draw(filteredData);
}
});
}
在不了解您的图表的更多细节的情况下,我无法给您一个非常详细的答案,但假设您有两个图表(chart1
和chart2
)由仪表板中的两个控件(control1
和control2
,分别)驱动,并且每个图表都有一个数据系列,那么你可以使用这样的东西来同步秤:
function syncChartScales () {
var range1 = chart1.getDataTable().getColumnRange(1);
var range2 = chart2.getDataTable().getColumnRange(1);
var minMax = {
min: Math.min(range1.min, range2.min),
max: Math.max(range1.max, range2.max)
}
chart1.setOption('vAxis.minValue', minMax.min);
chart1.setOption('vAxis.maxValue', minMax.max);
chart2.setOption('vAxis.minValue', minMax.min);
chart2.setOption('vAxis.maxValue', minMax.max);
chart1.draw();
chart2.draw();
}
google.visualization.events.addListener(control1, 'statechange', syncChartScales);
google.visualization.events.addListener(control2, 'statechange', syncChartScales);
如果您有更多数据系列,那么它会变得稍微复杂一些,因为您必须获取两个图表中所有数据系列的范围以找到它们的最小值/最大值,并将vAxis.minValue/maxValue
两个图表的选项设置为最小值/最大值所有系列。
以下是如何执行原始问题的要求:
chartWrapper.draw(); // initial draw of the chart
var chart = chartWrapper.getChart();
var cli = chart.getChartLayoutInterface();
var bb = cli.getChartAreaBoundingBox();
var vAxisMax = cli.getVAxisValue(bb.top);
参考:Google Groups 上的讨论:Google Visualization API。