Is it possible to detect a zoom/rangechange event with Google Line Chart api? If I use a annotated timeline i can do it, but not with a LineChart.
As you see i´m trying to synchronise two graphs. It works OK, but when i zoom in the upper graph, i want to zoom in on the lower graph aswell.
Im using the following code:
google.charts.load('current', {
callback: function () {
var chart1;
var chart2;
var data1 = new google.visualization.DataTable();
var data2 = new google.visualization.DataTable();
var outDiv1 = document.getElementById('mcs-chart-event');
var outDiv2 = document.getElementById('snr-chart-event');
var options1 = {title:'Wot',
height:300,
displayAnnotations: false,
displayZoomButtons: false,
chartArea: { width:'95%',height:'90%'},
lineWidth: 1.5,
legend: { position: 'none' },
crosshair: {
trigger: 'both',
orientation: 'vertical'
},
explorer: {
actions: ['dragToZoom', 'rightClickToReset'],
axis: 'horizontal',
keepInBounds: true,
maxZoomIn: 10.0
},
};
var options2 = {
displayZoomButtons: false,
displayRangeSelector: false,
title:'rsi typ',
chartArea: { width:'95%',height:'90%'},
height:100,
lineWidth: 1.5,
colors: ['red'],
legend: { position: 'none' },
crosshair: {
trigger: 'both',
orientation: 'vertical'
},
explorer: {
actions: ['dragToZoom', 'rightClickToReset'],
axis: 'horizontal',
keepInBounds: true,
maxZoomIn: 10.0
},
};
drawChartOne(data1);
drawChartTwo(data2);
google.visualization.events.addListener(chart1, 'onmouseover', function(selection) {
chart1.setSelection(selection);
chart2.setSelection([{ row: selection.row, column: null }]);
});
//Only works when using AnnotatedTimeLine...
google.visualization.events.addListener(chart1, 'rangechange', function(data) {
//Only works when using AnnotatedTimeLine...
chart2.setVisibleChartRange(data.start,data.end);
});
google.visualization.events.addListener(chart2, 'onmouseover', function(selection) {
chart2.setSelection(selection);
chart1.setSelection([{ row: selection.row, column: null }]);
});
chart1.draw(data1, options1);
chart2.draw(data2, options2);
function drawChartOne(data) {
data.addColumn('date', 'Date');
data.addColumn('number', 'Sessions');
data.addColumn({type: 'string', role: 'style'});
data.addColumn({type:'string', role:'annotation'});
var sessions = [786, 450, 866, 814, 192, 466, 984, 780, 922, 458, 786, 758, 701, 831, 901, 557, 114, 393, 689, 658, 103, 837, 164, 727, 593, 193, 945, 583, 948, 338];
var start = new Date(1458345600 * 1000);
var date;
var dates = [];
for(var i = 0; i < sessions.length; i++) {
var newDate = start.setDate(start.getDate() + 1);
if(i == 10){
data.addRow([new Date(newDate), sessions[i],'point { size: 6; shape-type: circle; fill-color: green;','Buy']);
}else{
data.addRow([new Date(newDate), sessions[i],null,null]);
}
}
chart1 = new google.visualization.LineChart(document.getElementById('mcs-chart'));
}
function drawChartTwo(data) {
data.addColumn('date', 'Date');
data.addColumn('number', 'Other Sessions');
var rsi = [100, 450, 200, 333, 192, 466, 984, 77, 922, 458, 200, 758, 701, 831, 901, 557, 114, 393, 500, 658, 103, 837, 300, 727, 593, 193, 945, 583, 948, 338];
var start = new Date(1458345600 * 1000);
var date;
for(var i = 0; i < rsi.length; i++) {
var newDate = start.setDate(start.getDate() + 1);
data.addRow([new Date(newDate), rsi[i]]);
}
chart2 = new google.visualization.LineChart(document.getElementById('snr-chart'));
}
},
packages: ['corechart','annotatedtimeline']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="mcs-chart"></div>
<div id="snr-chart"></div>
<div id="mcs-chart-event"></div>
<div id="snr-chart-event"></div>
first, use a MutationObserver to know when interactivity, including zoom, has occurred on chart1
// sync chart2
var observer = new MutationObserver(function () {
setRange(getCoords());
});
// start observing on 'ready'
google.visualization.events.addListener(chart1, 'ready', function() {
observer.observe(container1, {
childList: true,
subtree: true
});
});
next, grab the coordinates of each axis from chart1
, and set the viewWindow
on chart2
the coordinates are obtained using the following methods...
getChartLayoutInterface()
--> Returns an object containing information about the onscreen placement of the chart and its elements.
getChartAreaBoundingBox()
--> Returns an object containing the left, top, width, and height of the chart content (i.e., excluding labels and legend)
see functions for getCoords
and setRange
below...
see following working snippet, run once, then choose "Full page" to get the "full effect"...
google.charts.load('current', {
callback: function () {
var chart1;
var chart2;
var data1 = new google.visualization.DataTable();
var data2 = new google.visualization.DataTable();
var container1 = document.getElementById('mcs-chart');
var container2 = document.getElementById('snr-chart');
var outDiv1 = document.getElementById('mcs-chart-event');
var outDiv2 = document.getElementById('snr-chart-event');
var options1 = {title:'Wot',
height:300,
displayAnnotations: false,
displayZoomButtons: false,
chartArea: { width:'95%',height:'90%'},
lineWidth: 1.5,
legend: { position: 'none' },
crosshair: {
trigger: 'both',
orientation: 'vertical'
},
explorer: {
actions: ['dragToZoom', 'rightClickToReset'],
axis: 'horizontal',
keepInBounds: true,
maxZoomIn: 10.0
},
};
var options2 = {
displayZoomButtons: false,
displayRangeSelector: false,
title:'rsi typ',
chartArea: { width:'95%',height:'90%'},
height:100,
lineWidth: 1.5,
colors: ['red'],
legend: { position: 'none' },
crosshair: {
trigger: 'both',
orientation: 'vertical'
},
explorer: {
actions: ['dragToZoom', 'rightClickToReset'],
axis: 'horizontal',
keepInBounds: true,
maxZoomIn: 10.0
},
};
drawChartOne(data1);
drawChartTwo(data2);
google.visualization.events.addListener(chart1, 'onmouseover', function(selection) {
chart1.setSelection(selection);
chart2.setSelection([{ row: selection.row, column: null }]);
});
// sync chart2
var observer = new MutationObserver(function () {
setRange(getCoords());
});
// start observing on 'ready'
google.visualization.events.addListener(chart1, 'ready', function() {
observer.observe(container1, {
childList: true,
subtree: true
});
});
google.visualization.events.addListener(chart2, 'onmouseover', function(selection) {
chart2.setSelection(selection);
chart1.setSelection([{ row: selection.row, column: null }]);
});
drawCharts();
window.addEventListener('resize', drawCharts, false);
function drawCharts() {
chart1.draw(data1, options1);
chart2.draw(data2, options2);
}
function drawChartOne(data) {
data.addColumn('date', 'Date');
data.addColumn('number', 'Sessions');
data.addColumn({type: 'string', role: 'style'});
data.addColumn({type:'string', role:'annotation'});
var sessions = [786, 450, 866, 814, 192, 466, 984, 780, 922, 458, 786, 758, 701, 831, 901, 557, 114, 393, 689, 658, 103, 837, 164, 727, 593, 193, 945, 583, 948, 338];
var start = new Date(1458345600 * 1000);
var date;
var dates = [];
for(var i = 0; i < sessions.length; i++) {
var newDate = start.setDate(start.getDate() + 1);
if(i == 10){
data.addRow([new Date(newDate), sessions[i],'point { size: 6; shape-type: circle; fill-color: green;','Buy']);
}else{
data.addRow([new Date(newDate), sessions[i],null,null]);
}
}
chart1 = new google.visualization.LineChart(container1);
}
function drawChartTwo(data) {
data.addColumn('date', 'Date');
data.addColumn('number', 'Other Sessions');
var rsi = [100, 450, 200, 333, 192, 466, 984, 77, 922, 458, 200, 758, 701, 831, 901, 557, 114, 393, 500, 658, 103, 837, 300, 727, 593, 193, 945, 583, 948, 338];
var start = new Date(1458345600 * 1000);
var date;
for(var i = 0; i < rsi.length; i++) {
var newDate = start.setDate(start.getDate() + 1);
data.addRow([new Date(newDate), rsi[i]]);
}
chart2 = new google.visualization.LineChart(container2);
}
// get axis coordinates from chart1
function getCoords() {
var chartLayout = chart1.getChartLayoutInterface();
var chartBounds = chartLayout.getChartAreaBoundingBox();
return {
x: {
min: chartLayout.getHAxisValue(chartBounds.left),
max: chartLayout.getHAxisValue(chartBounds.width + chartBounds.left)
},
y: {
min: chartLayout.getVAxisValue(chartBounds.top),
max: chartLayout.getVAxisValue(chartBounds.height + chartBounds.top)
}
};
}
// set axis coordinates on chart2
function setRange(coords) {
options2.hAxis = {};
options2.vAxis = {};
options2.hAxis.viewWindow = {};
options2.vAxis.viewWindow = {};
if (coords) {
options2.hAxis.viewWindow.min = coords.x.min;
options2.hAxis.viewWindow.max = coords.x.max;
options2.vAxis.viewWindow.min = coords.y.min;
options2.vAxis.viewWindow.max = coords.y.max;
}
chart2.draw(data2, options2);
}
},
packages: ['corechart','annotatedtimeline']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="mcs-chart"></div>
<div id="snr-chart"></div>
<div id="mcs-chart-event"></div>
<div id="snr-chart-event"></div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With