First of all, I am not sure if what I am looking for is called stacked column chart or else.
Lib is either Google Charts or amCharts.
I have a series of values for the last 28 days representing e-mails sent, e-mails opened and e-mails with links clicked. For each date, the column's max. value should be the number of e-mails sent. This column is then divided based on the two other values. Basically what the chart should show is that from 20 mails sent, 17 were opened and 5 even had people click links inside them. With a regular stacked column approach and the numbers 20, 17 and 5, this would render a column peaking at 42 with one section covering 0-20, one 20-37 and one 37-42. What I want is a column peaking at 20, in front of it a column peaking at 17 and in front of that a column peaking at 5. Similar to a diff chart.
I could theoretically achieve this by modifying my data taking the 5 mails with clicks, the opened mails are 17 minus 5 = 12 and the mails sent are 20 minus 17 = 3. Then 5+12+3 = 20 what I wanted. However, hovering the stacked column will display the wrong values 5, 12 and 3 in the tooltip instead of 5, 17 and 20. So I would have to render custom tooltips.
You guys have any idea if there is a simple solution for my problem?
for the scenario you describe theoretically,
you would not need custom tooltips.
when loading the google data table, we can use object notation.
we can provide the value (v:
), and the formatted value (f:
)
{v: 12, f: '17'}
the tooltip will use the formatted value by default.
in addition, you could use a DataView
to perform the calculation.
which would allow you to load the data as normal.
here, calculated columns are used to adjust the value that is plotted,
but display the original value.
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
// create data table
var data = new google.visualization.DataTable();
data.addColumn('string', 'Date');
data.addColumn('number', 'Emails with Clicks');
data.addColumn('number', 'Emails Opened');
data.addColumn('number', 'Emails Sent');
// add data
data.addRow(['06/2020', 5, 17, 20]);
// create number format
var formatNumber = new google.visualization.NumberFormat({
pattern: '#,##0'
});
// create data view
var view = new google.visualization.DataView(data);
// build view columns
var viewColumns = [0];
for (var i = 1; i < data.getNumberOfColumns(); i++) {
addColumn(i);
}
function addColumn(index) {
viewColumns.push({
calc: function (dt, row) {
var currentColumnValue = dt.getValue(row, index);
var previousColumnValue = 0;
if (index > 1) {
previousColumnValue = dt.getValue(row, index - 1);
}
var adjusttedColumnValue = currentColumnValue - previousColumnValue;
var formattedColumnValue = formatNumber.formatValue(currentColumnValue);
return {
v: adjusttedColumnValue,
f: formattedColumnValue
};
},
label: data.getColumnLabel(index),
type: data.getColumnType(index),
});
}
// set view columns
view.setColumns(viewColumns);
// create options
var options = {
chartArea: {
left: 64,
top: 40,
right: 32,
bottom: 40,
height: '100%',
width: '100%'
},
height: '100%',
isStacked: true,
legend: {
alignment: 'end',
position: 'top'
},
width: '100%'
};
// create, draw chart with view
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
chart.draw(view, options);
window.addEventListener('resize', function () {
chart.draw(view, options);
});
});
html, body {
height: 100%;
margin: 0px 0px 0px 0px;
overflow: hidden;
padding: 0px 0px 0px 0px;
}
.chart {
height: 100%;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div class="chart" id="chart_div"></div>
Note: If you want to stack columns, one in front of the other, similar to a Diff Chart,
check this answer...