Related
Problem: If there isn't enough separation (time) between the tasks (bars), the dependency arrows don't display properly.
Question: Is it possible to start the dependency arrows from the left of each task bar instead of the middle?
Example of Problem:
google.charts.load('current', {'packages':['gantt']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Task ID');
data.addColumn('string', 'Task Name');
data.addColumn('string', 'Resource');
data.addColumn('date', 'Start Date');
data.addColumn('date', 'End Date');
data.addColumn('number', 'Duration');
data.addColumn('number', 'Percent Complete');
data.addColumn('string', 'Dependencies');
data.addRows([
['I0', 'External data acquisition request', 'RB',
new Date(2022, 4, 9), new Date(2022, 5, 29), null, 10, null],
['I1', 'data extraction', 'JK',
new Date(2022, 4, 15), new Date(2022, 5, 5), null, 100, null],
['I2', 'Create dataframe', 'RB',
new Date(2022, 4, 17), new Date(2022, 5, 10), null, 100, 'I1']
]);
var options = {
height: 700,
gantt: {
criticalPathEnabled: false, // Critical path arrows will be the same as other arrows.
arrow: {
angle: 50,
width: 1,
color: 'green',
radius: 30
}
}
};
var chart = new google.visualization.Gantt(document.getElementById('chart_div'));
chart.draw(data, options);
}
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
I'm developing a Gannt graph that shows the reservations for each room in a hotel from the first booking to the last one. But I wanted to be able to apply a filter to select a date range.
Below I leave the graph I have and an example of what I wanted. Thanks in advance.
google.charts.load('current', {'packages':['gantt']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Task ID');
data.addColumn('string', 'Task Name');
data.addColumn('string', 'Resource');
data.addColumn('date', 'Start Date');
data.addColumn('date', 'End Date');
data.addColumn('number', 'Duration');
data.addColumn('number', 'Percent Complete');
data.addColumn('string', 'Dependencies');
data.addRows([
['1', 'Room 1', 'room1',
new Date(2021, 2, 22), new Date(2021, 5, 20), null, 100, null],
['2', 'Room 2', 'room2',
new Date(2021, 5, 21), new Date(2021, 8, 20), null, 100, null],
['3', 'Room 3', 'room3',
new Date(2021, 8, 21), new Date(2021, 11, 20), null, 100, null],
['4', 'Room 4', 'room4',
new Date(2021, 11, 21), new Date(2022, 2, 21), null, 100, null],
['5', 'Room 5', 'room5',
new Date(2022, 2, 22), new Date(2022, 5, 20), null, 100, null],
['6', 'Room 6', 'room6',
new Date(2022, 5, 21), new Date(2022, 8, 20), null, 100, null],
['7', 'Room 7', 'room7',
new Date(2022, 8, 21), new Date(2022, 11, 20), null, 100, null],
['8', 'Room 8', 'room8',
new Date(2022, 11, 21), new Date(2023, 2, 21), null, 100, null],
['9', 'Room 9', 'room9',
new Date(2023, 11, 21), new Date(2024, 2, 21), null, 100, null],
]);
var options = {
height: 800,
gantt: {
trackHeight: 40,
innerGridTrack: {fill: '#fff'},
innerGridDarkTrack: {fill: '#ededed'},
shadowEnabled: true,
defaultStartDate: (new Date(2022,3,17))
},
};
var chart = new google.visualization.Gantt(document.getElementById('chart_div'));
chart.draw(data, options);
}
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
</head>
<body>
<div id="chart_div"></div>
<div id="control_div"></div>
<script src="index.js"></script>
</body>
</html>
Example below. I need this type of filter to filter the interval of dates that is shown on the graph:
google.load('visualization', '1.1', {
packages: ['corechart', 'controls']
});
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': '100%'
},
'hAxis': {
'baselineColor': 'none',
format: "dd.MM.yyyy"
}
},
// 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': '100%'
},
'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)]);
}
/* Change the format of the date column, used in chart, but not chart range filter */
var formatter = new google.visualization.DateFormat({
pattern: "dd.MM.yyyy"
});
formatter.format(data, 0);
dashboard.bind(control, chart);
dashboard.draw(data);
}
google.setOnLoadCallback(drawVisualization);
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>
Google Visualization API Sample
</title>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
</head>
<body>
<div id="dashboard">
<div id="chart" style='width: 915px; height: 300px;'></div>
<div id="control" style='width: 915px; height: 50px;'></div>
</div>
<script src="index2.js"></script>
</body>
</html>
I have the same kind of chart used in other locations in my project, and I did not changed anything.
The problem i'm getting is that no matter what i do the horizontal size does not changes...
obs- Both charts presented are in the same page but use unique identifiers and are in distinct divs.
obs- I already tried to remove the chart that is working but nothing changed.
i'm getting this layout:
[
When i should be getting this (already tried with the same exact code)
Using the inspector I'm getting this info:
The code i'm using is:
google.charts.load("current", {packages:["timeline"]});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var container = document.getElementById('example3.1');
var chart = new google.visualization.Timeline(container);
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'Position' });
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addRows([
['AA AGUIAR - 1', new Date(2019, 0, 01), new Date(2025, 0, 01)],['AA AGUIAR - 1', new Date(2009, 0, 01), new Date(2016, 7, 18)],['Torre 1 - 145', new Date(2019, 0, 01), new Date(2025, 0, 01)],['Torre 2 - 1A', new Date(2019, 0, 26), new Date(2025, 0, 01)],]);
chart.draw(dataTable);
}
with this div to present it:
<div id="example3.1" style="height: 200px;">
UPDATE:
Following the suggestion of WhiteHat I updated my code!
It looks like WhiteHat is right! the problem is in the tabs and I tried updating my code to this (once again WhiteHat suggestion), and it still doesn't work!
I tried to change the default tab when loading the page and the chart loaded great...
Updated code(not working):
google.charts.load('current', {
packages:['timeline']
}).then(function () {
// listen for tab shown event
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
// determine which tab is visible based on tab text
window.dispatchEvent(new Event('resize'));
switch ($(e.target).html()) {
case 'Vista por Contrato':
drawChart1();
break;
case 'Vista por Fracções':
drawChart2();
break;
}
});
function drawChart1() {
var container = document.getElementById('example3.1');
var chart = new google.visualization.Timeline(container);
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'Position' });
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addRows([
['AA AGUIAR - 1', new Date(2019, 0, 01), new Date(2025, 0, 01)],['AA AGUIAR - 1', new Date(2009, 0, 01), new Date(2016, 7, 18)],['Torre 1 - 145', new Date(2019, 0, 01), new Date(2025, 0, 01)],['Torre 2 - 1A', new Date(2019, 0, 26), new Date(2025, 0, 01)],?>
]);
chart.draw(dataTable);
}
function drawChart2() {
// code for chart 2
var data = new google.visualization.DataTable();
data.addColumn('string', 'Contrato');
data.addColumn('date', 'Season Start Date');
data.addColumn('date', 'Season End Date');
data.addRows([
['drwerwer', new Date(2018, 9, 25), new Date(2019, 11, 31)],['drwerwer', new Date(2018, 9, 25), new Date(2019, 11, 31)],['Teste', new Date(2009, 0, 01), new Date(2016, 7, 18)],['drwerwer', new Date(2018, 9, 25), new Date(2019, 11, 31)],['Teste', new Date(2009, 0, 01), new Date(2016, 7, 18)],['WBOX LDA', new Date(2019, 0, 01), new Date(2025, 0, 01)],]);
var options = {
height: 450,
timeline: {
groupByRowLabel: false
}
};
var chart = new google.visualization.Timeline(document.getElementById('chart_div'));
chart.draw(data, options);
}
// draw chart on initial tab
drawChart2();
});
This is the code I have for my tabs (since it looks the problem starts here!).
<ul class="nav nav-tabs justify-content-center">
<li class="nav-item"><a data-toggle="tab" href="#fraccoes">Vista por Fracções</a></li>
<li class="active"><a data-toggle="tab" href="#contratos">Vista por Contrato</a></li>
<li class="nav-item"><a data-toggle="tab" href="#notificacoes">Notificações</a></li>
</ul>
and this is the code for my bootstrap tabs:
$(document).ready(function(){
$(".nav-tabs a").click(function(){
$(this).tab('show');
});
});
in the code suggested by #whitehat there was an issue. I don't know if the problem was mine, or in suggestion, but i manage to solve it. The resize function wasn't working because it wasn't calling the correct charts. The names where not standard and because of that it was not working.
where is the corrected code:
google.charts.load('current', {
packages:['timeline']
}).then(function () {
// bootstrap tabs
$(".nav-tabs a").click(function(){
$(this).tab('show');
});
// listen for tab shown event
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
// determine which tab is visible based on tab text
window.dispatchEvent(new Event('resize'));
drawChart1();
drawChart2();
});
window.addEventListener('resize', drawChart);
function drawChart() {
switch ($(e.target).html()) {
case 'Vista por Fracções':
drawChart1();
break;
case 'Vista por Contrato':
drawChart2();
break;
}
}
// code for chart 1
var chart1 = new google.visualization.Timeline(document.getElementById('example3'));
var data1 = new google.visualization.DataTable();
data1.addColumn({ type: 'string', id: 'fracao' });
data1.addColumn({ type: 'string', id: 'contrato' });
data1.addColumn({ type: 'date', id: 'Start' });
data1.addColumn({ type: 'date', id: 'End' });
data1.addRows([
['AA AGUIAR - 1', new Date(2019, 0, 01), new Date(2025, 0, 01)],['AA AGUIAR - 1', new Date(2009, 0, 01), new Date(2016, 7, 18)],['Torre 1 - 145', new Date(2019, 0, 01), new Date(2025, 0, 01)],['Torre 2 - 1A', new Date(2019, 0, 26), new Date(2025, 0, 01)],
]);
var options1 = {
chartArea: {
left: 40,
width: '100%'
},
timeline: {
groupByRowLabel: true,
singleColor: 'green' ,
showRowLabels: true },
width: '100%',
height: '400',
};
// code for chart 2
var chart2 = new google.visualization.Timeline(document.getElementById('chart_div'));
var data2 = new google.visualization.DataTable();
data2.addColumn('string', 'NCONT');
data2.addColumn('string', 'Contrato');
data2.addColumn('date', 'Season Start Date');
data2.addColumn('date', 'Season End Date');
data2.addRows([
['drwerwer', new Date(2018, 9, 25), new Date(2019, 11, 31)],['drwerwer', new Date(2018, 9, 25), new Date(2019, 11, 31)],['Teste', new Date(2009, 0, 01), new Date(2016, 7, 18)],['drwerwer', new Date(2018, 9, 25), new Date(2019, 11, 31)],['Teste', new Date(2009, 0, 01), new Date(2016, 7, 18)],['WBOX LDA', new Date(2019, 0, 01), new Date(2025, 0, 01)],]);
]);
var options2 = {
height: 300,
timeline: {
groupByRowLabel: false,
singleColor: 'orange' ,
showRowLabels: false }
};
function drawChart1() {
chart1.draw(data1, options1);
}
function drawChart2() {
chart2.draw(data2, options2);
}
// draw chart on initial tab
drawChart2();
Now is working the bootstrap tabs!
I'm using Google Charts' Annotation Chart to display data. Everything's working but it's not showing the volume section, as seen in this google finance chart that, I believe, uses the same chart.
Here's what I have so far, but I don't know how to include that section:
google.charts.load('current', {'packages':['annotationchart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Col1');
data.addColumn('string', 'Col2');
data.addColumn('string', 'Col3');
data.addColumn('number', 'Col4');
data.addColumn('string', 'Col5');
data.addColumn('string', 'Col6');
data.addRows([
[new Date(2017, 2, 15), 85, 'More', 'Even More',
91, undefined, undefined],
[new Date(2017, 2, 16), 93, 'Sales', 'First encounter',
99, undefined, undefined],
[new Date(2017, 2, 17), 75, 'Sales', 'Reached milestone',
96, 'Att', 'Good'],
[new Date(2017, 2, 18), 60, 'Sales', 'Low',
80, 'HR', 'Absences'],
[new Date(2017, 2, 19), 95, 'Sales', 'Goals',
85, 'HR', 'Vacation'],
[new Date(2017, 2, 20), 40, 'Sales', 'Training',
67, 'HR', 'PTO']
]);
var chart = new google.visualization.AnnotationChart(document.getElementById('chart_div'));
var options = {
displayAnnotations: true
};
chart.draw(data, options);
}
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div id='chart_div' style='width: 900px; height: 500px;'></div>
This is what the google finance chart looks like, but I can't seem to include the volume section marked in red:
the annotation chart does not include an option for the middle chart / volume section
this could be added manually by drawing another, separate chart
however, the second chart cannot be placed in between the annotation chart and it's range filter
as such, you would need to turn off the annotation's range filter
and draw your own ChartRangeFilter
typically, custom filters are bound to charts using a dashboard
however, while building the example for this answer,
i noticed the annotation chart doesn't re-draw properly
after the filter has been applied, and then removed,
the annotation chart does not return to the original state
to correct, need to create the annotation chart every time it is drawn
see following working snippet,
a column chart is used for the volume section
the range filter is bound manually using the 'statechange' event
google.charts.load('current', {
callback: drawDashboard,
packages: ['annotationchart', 'controls', 'corechart']
});
function drawDashboard() {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Col1');
data.addColumn('string', 'Col2');
data.addColumn('string', 'Col3');
data.addColumn('number', 'Col4');
data.addColumn('string', 'Col5');
data.addColumn('string', 'Col6');
data.addRows([
[new Date(2017, 2, 15), 85, 'More', 'Even More',
91, undefined, undefined],
[new Date(2017, 2, 16), 93, 'Sales', 'First encounter',
99, undefined, undefined],
[new Date(2017, 2, 17), 75, 'Sales', 'Reached milestone',
96, 'Att', 'Good'],
[new Date(2017, 2, 18), 60, 'Sales', 'Low',
80, 'HR', 'Absences'],
[new Date(2017, 2, 19), 95, 'Sales', 'Goals',
85, 'HR', 'Vacation'],
[new Date(2017, 2, 20), 40, 'Sales', 'Training',
67, 'HR', 'PTO']
]);
var rangeFilter = new google.visualization.ControlWrapper({
controlType: 'ChartRangeFilter',
containerId: 'control_div',
dataTable: data,
options: {
filterColumnLabel: 'Date',
ui: {
chartOptions: {
height: 60,
width: '100%',
chartArea: {
width: '100%'
},
chartType: 'AreaChart'
}
}
},
view: {
columns: [0, 1, 4]
}
});
google.visualization.events.addListener(rangeFilter, 'ready', drawCharts);
google.visualization.events.addListener(rangeFilter, 'statechange', drawCharts);
rangeFilter.draw();
function drawCharts() {
var filterState = rangeFilter.getState();
var filterRows = data.getFilteredRows([{
column: 0,
minValue: filterState.range.start,
maxValue: filterState.range.end
}]);
var viewAnn = new google.visualization.DataView(data);
viewAnn.setRows(filterRows);
var chartAnn = new google.visualization.AnnotationChart(document.getElementById('chart_ann'));
var optionsAnn = {
displayAnnotations: false,
displayRangeSelector: false
};
chartAnn.draw(viewAnn, optionsAnn);
var viewCol = new google.visualization.DataView(data);
viewCol.setColumns([0, 1, 4]);
viewCol.setRows(filterRows);
var chartCol = new google.visualization.ColumnChart(document.getElementById('chart_col'));
var optionsCol = {
hAxis: {
textStyle: {
color: 'transparent'
}
},
height: 72,
legend: 'none',
theme: 'maximized',
vAxis: {
textStyle: {
color: 'transparent'
}
}
};
chartCol.draw(viewCol, optionsCol);
}
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_ann"></div>
<div id="chart_col"></div>
<div id="control_div"></div>
I have setup a simple Google Chart by following the example on this page:
http://code.google.com/apis/chart/interactive/docs/gallery/linechart.html
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Year');
data.addColumn('number', 'Sales');
data.addColumn('number', 'Expenses');
data.addRows([
['2004', 1000, 400],
['2005', 1170, 460],
['2006', 860, 580],
['2007', 1030, 540]
]);
var options = {
width: 400, height: 240,
title: 'Company Performance'
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
But now, after it's rendered, with some javascript i want to dynamically add another series of data. Can anyone point me in the right direction on how to do this?
The data i want to add, a number column with the number of employees, should show a new line in the chart, in another color and doesn't start at year 2004 but at 2005,
You need to add new data to 'data' variable and call the chart.draw() method again.
See the DataTable docs or play a bit at http://code.google.com/apis/ajax/playground/?type=visualization#line_chart
Example:
// Add columns
data.addColumn('string', 'Employee Name');
data.addColumn('date', 'Start Date');
// Add empty rows
data.addRows(6);
data.setCell(0, 0, 'Mike');
data.setCell(0, 1, {v:new Date(2008,1,28), f:'February 28, 2008'});
data.setCell(1, 0, 'Bob');
data.setCell(1, 1, new Date(2007, 5, 1));
data.setCell(2, 0, 'Alice');
data.setCell(2, 1, new Date(2006, 7, 16));
data.setCell(3, 0, 'Frank');
data.setCell(3, 1, new Date(2007, 11, 28));
data.setCell(4, 0, 'Floyd');
data.setCell(4, 1, new Date(2005, 3, 13));
data.setCell(5, 0, 'Fritz');
data.setCell(5, 1, new Date(2007, 9, 2));