Reputation: 66590
I'm trying to create plot using Billboard.js that will show prices overtime from different shops.
Here is my attempt:
dayjs.locale('pl');
fetch('https://jcubic.pl/price.json')
.then(res => res.json())
.then(data => {
var chart_data = {
xs: {},
columns: [],
type: 'line'
};
Object.keys(data).map((shop, i) => {
const date = `${shop}_date`;
var prices = [shop];
var dates = [date];
data[shop].forEach(arr => {
const [ price, date ] = arr;
prices.push(price);
dates.push(dayjs(arr[1]).format('MMM DD'));
});
chart_data.xs[shop] = date;
chart_data.columns.push(prices);
chart_data.columns.push(dates);
});
console.log(chart_data);
bb.generate({
bindto: "#chart",
data: chart_data
});
//console.log(data);
});
Codepen demo https://codepen.io/jcubic/pen/VwjXNLE?editors=1010
the problem is that it don't work. It seems that what I need is in two examples but it don't show how to use them both. The problem is that timeseries example and category xaxis example all show one x axis and for all of them it show same points. In my case overtime I some shops may don't offer the product for prices I'm plotting.
The line plot in the example above work with 2d points but it require numbers and both categoryAxis and time series axis have only one X axis data and it require that all the data have same points on x axis.
So how can I 2D line plot with multiple lines? I'm fine with any library that this will work. I would like to have line plot with multiple color lines like in Billboard.js, but can't figure out how to use this library for my case.
Here is example in chart.js but it's not line chart because the lines in plot are squared.
the demo from the image is on Codpen: https://codepen.io/jcubic/pen/abNKLNJ?editors=0110
Upvotes: 0
Views: 143
Reputation: 5838
Apexcharts tends to be a fantastic library for this sort of thing. It's free, supports timeseries, accepts null values, has localisation, lots of styling options and good documentation. I typically find that everything needed is often already supported by it.
Here's a solution using that: https://jsfiddle.net/b5pghLja/4/
fetch('https://cdn.jsdelivr.net/npm/apexcharts/dist/locales/pl.json')
.then(res => res.json())
.then(pl => {
fetch('https://jcubic.pl/price.json')
.then(res => res.json())
.then(data => {
/* console.log(data); */
var chart_data = {
chart: {
locales: [pl],
defaultLocale: 'pl',
height: 400,
width: "100%",
type: 'line',
stacked: false,
animations: {
enabled: false,
initialAnimation: {
enabled: false
}
},
zoom: {
type: 'x',
enabled: true,
autoScaleYaxis: true
},
toolbar: {
show: true,
autoSelected: 'zoom'
}
},
series: [],
dataLabels: {
enabled: false
},
tooltip: {
shared: true,
y: {
formatter: function (val) {
return (val).toFixed(0)
}
}
},
markers: {
size: 3,
strokeWidth: 0
},
stroke: {
width: 3,
curve: 'smooth'
},
xaxis: {
type: 'datetime'
},
yaxis: {
labels: {
formatter: function (val) {
return (val).toFixed(0);
}
},
title: {
text: 'Koszt'
}
}
};
Object.keys(data).map((shop, i) => {
var series = {
name: shop,
data: []
};
data[shop].forEach(arr => {
const [price, date] = arr;
series.data.push([new Date(date).getTime(), price]);
});
chart_data.series.push(series);
});
var chart = new ApexCharts(document.querySelector("#chart"), chart_data);
chart.render();
});
});
#chart {
max-width: 100%;
margin: 10px auto;
}
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<div id="chart">
</div>
If you wish to, it'd likely be possible to build an array of each unique datetime in the API data, then fill in each series with null values where certain datetimes have no price entry.
Upvotes: 1