How to achieve multi line area chart with Ant Design Charts? - reactjs

What I'm trying to do is I want to plot a line which represents the values of predictions and 2 other lines which represent the upper 95% Confidence Interval and the lower 95% Confidence Interval. I want to achieve this using Ant Design Charts. What I have so far is a Multi Line Chart, but I want the confidence Interval to be an area.
My data:
const data = [
{"date":"2021-11-17", "category":"upper_95", "value":23.87625},
{"date":"2021-11-17", "category":"lower_95", "value":20.32322},
{"date":"2021-11-17", "category":"prediction","value":21.21381},
{"date":"2021-11-18", "category":"upper_95", "value":25.87625},
{"date":"2021-11-18", "category":"lower_95", "value":22.32322},
{"date":"2021-11-18", "category":"prediction","value":19.21381},
{"date":"2021-11-19", "category":"upper_95", "value":26.87625},
{"date":"2021-11-19", "category":"lower_95", "value":24.32322},
{"date":"2021-11-19", "category":"prediction","value":25.21381},
...
]
My code so far:
const Graph = () => {
const config = {
data,
xField: "date",
yField: "value",
seriesField: "category",
...
};
return <Line {...config} />
};

"Ant Design Charts" support area charts:
https://charts.ant.design/en/examples/area/stacked#basic-slider
Instead of:
return <Line {...config} />
Try with:
return <Area {...config} />

Related

Ho to create a histogram with echarts

How can I create a simple histogram with apache echarts? I checked their documentation and it does not appear there. Does echarts not have histogram?
Using Echarts tools with datasets
Echarts data transformation can be used to shape a dataset into a histogram dataset, using 'ecStat:histogram'. Here is a very good example showing how to use this tool. You can also find a clear documentation on github.
This solution is a bit more complex to handle (understanding datasets and data transform) but it's the clean way to make a histogram.
Simple hand made solution
You can create a chart that looks like a histogram using Bar charts. Your data will need some formatting so that it looks like a list of [x,y] :
x : (rangeMax - rangeMin)/2
y : number of points in that range
You are also going to need to set barWidth to 100% and xAxis.type to 'value' for it to look like a histogram.
var myChart = echarts.init(document.getElementById('main'));
option = {
xAxis: [
{
type: 'value',
}
],
yAxis: [
{
type: 'value'
}
],
series: [
{
name: 'Direct',
type: 'bar',
barWidth: '100%',
data: [[5,20], [15,52], [25,200], [35,334], [45,390], [55,330], [65,220]]
}
]
};
myChart .setOption(option)
<html>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.3.2/echarts.min.js"></script>
<div id="main" style="width: 600px; height:400px;"></div>
</body>
</html>

React Datagrid with cards instead of columns?

We love the DataGrid for its build in sorting and filtering capabilities.
However grid based layouts are troublesome on small screen devices. So we started looking at Card based layouts. There we miss the sorting and filtering we appreciate in the DataGrid.
Now we are wondering if there is an example to use cards as UI layer for the DataGrid, where a column in the grid would become a row in the card. Cards should flow to available columns.
How can we do this?
This is a partial answer, however, there is a renderCell prop in the column configuration that accepts a function that can include a component.
So, to replace a row with a card, I might include a column that renders your components with all of the values you would otherwise express one by one in a series of columns. For instance:
const columns = [
{ field: 'id', headerName: 'ID', hide: true }, // keep this
{ field: 'myCombinedView', hide: false, flex: 1, renderCell: (props) => <Component {...props} /> },
I can imagine including a single, hidden column that represents a concatenation of the values you want to sort on. From here, specify the sort function for the Component column that uses the hidden value.
The following code sample is pulled from the DataGrid storyboard:
() => {
const columns = getColumns();
// compute a new field for purposes of sorting
columns[columns.length] = {
field: 'username',
valueGetter: (params) =>
`${params.getValue('name') || 'unknown'}_${params.getValue('age') || 'x'}`,
sortComparator: (v1, v2, cellParams1, cellParams2) => cellParams1.row.age - cellParams2.row.age,
width: 150,
};
return (
<div className="grid-container">
<XGrid
rows={getRows()}
columns={columns}
// use the field as the sort model
sortModel={[{ field: columns[columns.length - 1].field, sort: 'asc' }]}
/>
</div>
);
}
How to dynamically select/change the sort criteria is not something I can see a clear path for.

Add rectangle fill to line chart

Is it possible to add draw a rectangle as a background of Line chart? I'm using react-chartjs-2 and cannot find any examples with drawing a canvas as background...
managed to do this with following code:
const plugins = [
{
beforeDraw: (chartInstance, easing) => {
const ctx = chartInstance.chart.ctx;
ctx.fillStyle = "lightgreen";
ctx.fillRect(30, 200, 955, 50);
},
},
];
//...
<Line
data={data}
plugins={plugins}
/>
You can draw it before the Line chart with drawTime: 'beforeDatasetsDraw'

How to use UTC date string as recharts axis and distribute it evenly

My source of data looks like this:
const data = [
{ dataora: "2019-10-20T04:00:00Z", valore: -0.04 },
{ dataora: "2019-10-20T05:00:00Z", valore: -0.03 },
{ dataora: "2019-10-20T06:00:00Z", valore: -0.03 },
{ dataora: "2019-10-20T07:00:00Z", valore: -0.03 },
{ dataora: "2019-10-21T10:00:00Z", valore: -0.04 },
{ dataora: "2019-10-21T23:00:00Z", valore: -0.04 },
{ dataora: "2019-10-22T00:00:00Z", valore: -0.04 }
];
My recharts component looks like this:
<LineChart width={600} height={300} data={data}>
<Line type="monotone" dataKey="valore" stroke="black" strokeWidth={2} dot={false} />
<CartesianGrid stroke="#ccc" />
<XAxis
dataKey={'dataora'}
tickFormatter={dateFormatter}
/>
<YAxis />
</LineChart>
dateFormatter looks like this:
const dateFormatter = date => {
// return moment(date).unix();
return moment(date).format('DD/MM/YY HH:mm');
};
Usually I have a data entry every other hour, but 2019-10-21 has only two values for the whole day, now I'd like to show also the missing hours in my graph. In other data entries I may get different time gap so I can't set the tick interval manually.. I just need the date field to be distributed evenly on the XAxis.
I tried to change the tickFormatter to return the date in Unix epoch seconds and use the below props..
scale="time" type="number" domain={[dateFormatter(data[0].dataora), dateFormatter(data[1].dataora)]}
but the XAxis dissapeared along with the data line.
Is there any way to "fill in" those date blanks?
A codesandbox
[answering myself here]
It turns out that I had to process the input data beforehand since recharts does not have anything that allows me to teach him how to read my input data.
So I converted my date field to epoch.
data.forEach(d => {
d.dataora = moment(d.dataora).valueOf(); // date -> epoch
});
And then I can use the date field type as a number and set the domain etc.
<XAxis
dataKey={'dataora'}
domain={[data[0].dataora, data[data.length - 1].dataora]}
scale="time"
type="number"
tickFormatter={DateFormatter} />
I'm not really happy with this solution because it requires me to actually process all the data before rendering the chart. I haven't tried it with large size data (thousands of entries or more) yet but I'm not optimistic.

ChartJS Line chart causes browser crash

I am updating a Line chart using HTTP get through ngResource and a rest API.
My technique is to get the JSON dataset and create a new chart every time a user is clicking on a button.
It works great, but at one time, it causes the browser crash. I have tested on Chrome, Firefox on both Windows and Linux.
In my controller :
$scope.labels = $scope.dataFromREST;
$scope.series = ['Series A'];
$scope.data = [$scope.dataFromREST2];
$scope.onClick = function (points, evt) {
console.log(points, evt);
};
$scope.datasetOverride = [{ yAxisID: 'y-axis-1' }];
$scope.options = {
scales: {
yAxes: [
{
id: 'y-axis-1',
type: 'linear',
display: true,
position: 'left'
}
],
xAxes: [{
responsive: true,
ticks: {
autoSkip: true,
maxTicksLimit: 20
}
}]
}
};
In my index.html :
<canvas id="line" class="chart chart-line" chart-data="data"
chart-labels="labels" chart-series="series" chart-options="options"
chart-dataset-override="datasetOverride" chart-click="onClick">
</canvas>
Is there a way to just update or refresh the Line Chart with the $scope.dataFromREST data received and not create a new Chart object every time? (Because I think, the crash come from creating a new chart every time) I see the ".update()" function, but I can't seem to get it to work.
I have also tried the ".destroy()" and I am still getting the browser wind up to crash.
How can I get rid of that crash? Please help!
Yes, there is a way to simply update the underlying chart.js chart data without having to re-instantiate the chart each and every time. You just need to use the update(duration, lazy) function from the API.
Here is an example that I use in one of my apps (modified for your specific case). Note, chart is my chart.js object (what was returned from new Chart()...:
assembledData = {};
assembledData.data = // data from api call in an acceptable data format that chart.js understands
assembledData.colors = // new color definition for your data so it will update correctly
assembledData.labels = // new label definition for your data so it will update correctly
chart.data.datasets[0].data = assembledData.data;
chart.data.datasets[0].backgroundColor = assembledData.colors;
chart.data.labels = assembledData.labels;
chart.update();
Depending on how your chart behaves you may not have to re-define colors and labels on each update.

Resources