Reputation: 20820
Using Chartist I know that there is an option to "fill holes" in two different data sets that don't have an equivalent amount of items like the following example:
var chart = new Chartist.Line('.ct-chart', {
labels: [1, 2, 3, 4, 5, 6, 7],
series: [
[5, 5, 10, 8, 7, 5, 4],
[10, 15, null, 12, null, null, null]
]
}, {
lineSmooth: Chartist.Interpolation.cardinal({
fillHoles: true,
})
});
<script src="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.js"></script>
<link href="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.css" rel="stylesheet"/>
<div class="ct-chart"></div>
Notice in the example the second series will only show a line up to the last value that is not null
(at index 4).
Is there a way to get chartist to make the second series relative to the first, spreading the second series line to match the first one up until the last value of the longest series?
Upvotes: 1
Views: 165
Reputation: 23372
You could write some helpers that modify your data arrays:
trimNulls
removes any null
values from the start and end of an array:
[10, 15, null, 12, null, null, null] -> [10, 15, null, 12]
stretch
takes an array and a required length and distributes the original values to new indexes:
[10, 15, null, 12] -> 7 -> [10, null, 15, null, null, null, 12]
alignSeries
takes a list of data series and aligns each of them to the widest one.
[ [ 1, 2, 3, 4], [1, 4], [null, 1, 4] ] ->
[ [ 1, 2, 3, 4], [1, null, null, 4], [1, null, null, 4] ]
In a running example, with the old line included for reference:
const trimNulls = (data) => {
// Find the first non-null value
const start = data.findIndex(y => y !== null);
// Find the last non-null value
const end = data.length - Array.from(data).reverse()
.findIndex(y => y !== null);
// Return the elements between those boundaries
return data.slice(start, end);
}
const stretch = (data, newLength) => {
// Create array of required number of nulls
const stretched = Array(newLength).fill(null);
// Determine the stretch factor
const s = newLength / data.length;
// For every value we want to keep, place it
// at its new, stretched index
data.forEach((y, x) => {
stretched[Math.ceil(x * s)] = y;
});
// Return the newly created array
return stretched;
}
// Takes a list of series and aligns their starts and ends, stretching
// in between
const alignSeries = series => {
// Trim each series
const trimmed = series.map(trimNulls);
// Find the longest one
const maxLength = Math.max(...trimmed.map(t => t.length));
// Stretch all series to the longest length and return
return trimmed.map(t => stretch(t, maxLength));
};
var chart = new Chartist.Line('.ct-chart', {
labels: [1, 2, 3, 4, 5, 6, 7],
series: [
...alignSeries([
[5, 5, 10, 8, 7, 5, 4],
[10, 15, null, 12, null, null, null]
]),
// For reference
[10, 15, null, 12, null, null, null]
]
}, {
lineSmooth: Chartist.Interpolation.cardinal({
fillHoles: true,
})
});
<script src="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.js"></script>
<link href="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.css" rel="stylesheet"/>
<div class="ct-chart"></div>
Upvotes: 2