I'm building a dashboard application, using Highcharts for -well- charts. On high zoom levels, or on a short time interval, areaspline charts look all over the place.
I'm looking into interpolation options, coming from d3, but not finding much. Data are retrieved via AJAX to my API as a JSON, and rendered into the chart. A custom built modal switch can toggle data resolution between "year" and "hour", by running a new API request and refreshing the chart.
data with 24-hour sampling rate
a detail of the same data, with 1-hour sampling rate
As visible from the screenshots above, in shorter sampling intervals when data variation is wider, the spline interpolation simply breaks, curves become straight line, spline points become angular and often areas and the delimiting curve are "decoupled".
I'm looking for a way to solve this, or at least to have the charts readable - in all formats. I can change the chart format (as long as it is stacked) but so far the area chart is the best fit for this kind of data.
A jsfiddle recreating the issue is here:
https://jsfiddle.net/_dario/s3o61gj4/
Here is the js code:
// this defines some colors
var igColor = "#fec564", //instagram
twColor = "#55acee", //twitter
fbColor = "#3b5998", //facebook
wbColor = "#a48ad5", //blog
wfColor = "#e57e31", //forum
wnColor = "#17c457", //news
inColor = "#007bb5", //linkedin
ytColor = "#ff1216", //youtube
otColor = "#81959b"; //others
//this defines the chart configuration with NULL data - data are added via AJAX later on
var config = {
chart: {
zoomType:'x',
height:500
},
title: {
text: 'Ugly chart'
},
xAxis: {
type: 'datetime'
},
yAxis: {
min: 0,
title: {
text: 'Posts'
}
},
legend: {
enabled:true
},
plotOptions: {
series: {
stacking: 'normal'
}
},
series: [
{
type: 'areaspline',
name: 'Instagram',
data: null,
color:igColor
},{
type: 'areaspline',
name: 'Twitter',
data: null,
color:twColor
},{
type: 'areaspline',
name: 'Facebook',
data: null,
color:fbColor
},{
type: 'areaspline',
name: 'Blogs',
data: null,
color:wbColor
},{
type: 'areaspline',
name: 'News',
data: null,
color:wnColor
},{
type: 'areaspline',
name: 'Forums',
data: null,
color:wfColor
},{
type: 'areaspline',
name: 'Youtube',
data: null,
color:ytColor
},{
type: 'areaspline',
name: 'Linkedin',
data: null,
color:inColor
},{
type: 'areaspline',
name: 'Others',
data: null,
color:otColor
}
]
}; //end config definition
//THESE DATA ARE ORIGINALLY RETURNED BY AN AJAX CALL TO MY API
var d = {
"ig":[[1550880000000,1],[1550883600000,1],[1550890800000,1],[1550898000000,1],[1550901600000,3],[1550905200000,1],[1550908800000,6],[1550912400000,6],[1550916000000,6],[1550919600000,9],[1550923200000,4],[1550926800000,7],[1550930400000,5],[1550934000000,5],[1550937600000,12],[1550941200000,8],[1550944800000,6],[1550948400000,7],[1550952000000,6],[1550955600000,3],[1550959200000,3],[1550962800000,4],[1550966400000,1],[1550970000000,1],[1550977200000,1],[1550988000000,3],[1550991600000,4],[1550995200000,6],[1550998800000,6],[1551002400000,9],[1551006000000,4],[1551009600000,9],[1551013200000,11],[1551016800000,9],[1551020400000,7],[1551024000000,6],[1551027600000,7],[1551031200000,4],[1551034800000,6],[1551038400000,9],[1551042000000,4],[1551045600000,6]],
"tw":[[1550880000000,1],[1550901600000,1],[1550905200000,1],[1550908800000,2],[1550912400000,4],[1550916000000,1],[1550919600000,4],[1550923200000,2],[1550926800000,1],[1550930400000,5],[1550934000000,1],[1550937600000,1],[1550941200000,1],[1550944800000,5],[1550948400000,1],[1550952000000,1],[1550959200000,3],[1550962800000,1],[1550966400000,1],[1550988000000,1],[1550991600000,2],[1550995200000,4],[1550998800000,5],[1551006000000,3],[1551009600000,4],[1551013200000,3],[1551016800000,3],[1551020400000,2],[1551024000000,3],[1551027600000,3],[1551031200000,2],[1551034800000,2],[1551038400000,3],[1551042000000,1],[1551045600000,1],[1551049200000,2],[1551052800000,1]],
"ty":[[1550880000000,4],[1550898000000,1],[1550908800000,1],[1550912400000,3],[1550916000000,2],[1550919600000,3],[1550923200000,2],[1550926800000,1],[1550930400000,2],[1550937600000,3],[1550941200000,4],[1550944800000,2],[1550948400000,2],[1550952000000,1],[1550955600000,1],[1550959200000,1],[1550962800000,2],[1550966400000,2],[1550995200000,3],[1550998800000,13],[1551002400000,1],[1551006000000,1],[1551013200000,4],[1551016800000,3],[1551024000000,1],[1551027600000,2],[1551031200000,1],[1551034800000,1],[1551038400000,3],[1551042000000,1],[1551049200000,5],[1551052800000,5]],
"wb":[[1550880000000,6],[1550887200000,1],[1550898000000,1],[1550912400000,1],[1550916000000,1],[1550919600000,1],[1550926800000,2],[1550930400000,1],[1550944800000,1],[1550991600000,1],[1550998800000,1],[1551016800000,1],[1551024000000,1],[1551027600000,1],[1551049200000,1],[1551052800000,1]],
"wf":[[1551034800000,1],[1551049200000,2],[1551052800000,2]],
"wn":[[1550880000000,16],[1550883600000,1],[1550898000000,1],[1550901600000,1],[1550905200000,2],[1550908800000,1],[1550912400000,1],[1550916000000,1],[1550919600000,1],[1550923200000,1],[1550934000000,1],[1550941200000,1],[1550944800000,1],[1550962800000,4],[1550966400000,4],[1550984400000,2],[1550988000000,1],[1550991600000,1],[1550995200000,1],[1551006000000,1],[1551009600000,2],[1551013200000,1],[1551049200000,19],[1551052800000,19]],
"in":[],"yt":[],"ot":[]}; //end data
//this part happens inside a SUCCESS statement in the AJAX call that retrieves the data above
//parse the returned data into the chart config above, substituting NULL values
config.series[0].data = d.ig;
config.series[1].data = d.tw;
config.series[2].data = d.ty;
config.series[3].data = d.wb;
config.series[4].data = d.wn;
config.series[5].data = d.wf;
config.series[6].data = d.yt;
config.series[7].data = d.in;
config.series[8].data = d.ot;
//create the chart
if(window.sourcesChart){
window.sourcesChart.update(config);
} else {
window.sourcesChart = new Highcharts.chart('platformChartContainer', config);
}
Because there are a lot more gaps in the data at that level the disconnect between null values it more obvious. If you user the 'connectNulls' property on plotOptions.series it will make the chart a bit more readable.
plotOptions: {
series: {
stacking: 'normal',
connectNulls: true
}
}