I'm trying to create a fairly simple time series chart for payments made at X time for Y amount. X-axis labels are fixed at every 12 hours like this:
new Date("2018-08-28 00:00"),
new Date("2018-08-28 12:00"),
new Date("2018-08-29 00:00"),
new Date("2018-08-29 12:00")
.............................
When I hard-code array of amount/time I get decent graph but without X-axis labels: https://jsfiddle.net/tolyan/69z2wepo/281812/. When I try to use some real data and map it to array, labels are generated instead of my fixed labels: https://jsfiddle.net/tolyan/69z2wepo/281806/. Also, how do I configure chartist to have some padding or gap for the graph start - for better readability. Thanks in advance for any tips!
I think there's nothing wrong with your mapping of the real data, I think is more of knowing your data and putting the correct "ticks" in the x axis, for example in your data you have stamps in terms of seconds, for example:
{amount: 22, timestamp: "2018-08-29T06:01:54.007"},
{amount: 1, timestamp: "2018-08-29T06:01:55.29"},
{amount: 11, timestamp: "2018-08-29T06:01:56.66"},
{amount: 9, timestamp: "2018-08-29T06:01:58.063"},
So of course if you are going to have your ticks set from the 28th at 00:00 till the 31st at 23:59, then it won't work and it won't show the labels because the graph needs to create that space in between for it to show the ticks, that's why it shows the dot at the beginning and at the end. So adjusting your example in the fiddle, try to put lower values to your ticks, something like this:
axisX: {
type: Chartist.FixedScaleAxis,
divisor: 4,
ticks: [
new Date("2018-08-29 06:01:52"),
new Date("2018-08-29 06:01:53"),
new Date("2018-08-29 06:01:55"),
new Date("2018-08-29 06:01:59")
],
So the full example should be something like:
var trans = [
{amount: 22, timestamp: "2018-08-29T06:01:54.007"},
{amount: 1, timestamp: "2018-08-29T06:01:55.29"},
{amount: 11, timestamp: "2018-08-29T06:01:56.66"},
{amount: 9, timestamp: "2018-08-29T06:01:58.063"},
{amount: 6, timestamp: "2018-08-29T06:02:02.203"},
{amount: 1, timestamp: "2018-08-29 06:02:03.413"}
];
var data = {
series: [
{
name: 'series-times',
data: trans.map((prop, key) => {
return {
x: new Date(prop["timestamp"]),
y: prop["amount"]
};
})
}
]
};
var options = {
lineSmooth: Chartist.Interpolation.cardinal({
tension: 0
}),
axisY: {
type: Chartist.FixedScaleAxis,
divisor: 8,
ticks: [0, 10, 20, 30, 40, 50, 60],
labelInterpolationFnc: function(value) {
return "$" + value;
}
},
axisX: {
type: Chartist.FixedScaleAxis,
divisor: 4,
ticks: [
new Date("2018-08-29 06:01:52"),
new Date("2018-08-29 06:01:53"),
new Date("2018-08-29 06:01:55"),
new Date("2018-08-29 06:01:59")
],
labelInterpolationFnc: function(value) {
return moment(value).format('MM/DD/YY HH:mm:ss');
}
},
// low: 0,
// high: 100,
showPoint: true,
height: "300px",
animation: {
draw: function(data) {
if (data.type === "line" || data.type === "area") {
data.element.animate({
d: {
begin: 600,
dur: 700,
from: data.path
.clone()
.scale(1, 0)
.translate(0, data.chartRect.height())
.stringify(),
to: data.path.clone().stringify(),
easing: Chartist.Svg.Easing.easeOutQuint
}
});
} else if (data.type === "point") {
data.element.animate({
opacity: {
begin: (data.index + 1) * delays,
dur: durations,
from: 0,
to: 1,
easing: "ease"
}
});
}
}
}
}
/* var options = {
seriesBarDistance: 100
}; */
new Chartist.Line('.ct-chart', data, options);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<link href="https://cdn.jsdelivr.net/chartist.js/latest/chartist.min.css" rel="stylesheet"/>
<div class="ct-chart ct-square"></div>
<script src="https://cdn.jsdelivr.net/chartist.js/latest/chartist.min.js"></script>
For changing the padding of the labels, just target them with CSS, you can just check them out which is the label class and adjust it to your needs. Or also another more cleaner solution is to change the JavaScript options of the tick, or the labels, more info in:
https://gionkunz.github.io/chartist-js/api-documentation.html
Hope it helps, let me know if you have questions.
Leo.
Related
I am making a chart displaying stock data using ChartJs (react-chartjs-2). I have a datapoint for every minute from 9:30am to 3:59pm. When I plot it, my chart looks like the image below. The points don't even remotely align with the grid. The point in the image says 10:16 but the chart positions it between 9 and 10. Why is it like this? The points should also start halfway after the 9 tick since my data starts at 9:30. Does anyone know what I can do to resolve this?
My data is in the format like x = 2023-02-15 09:30:00-05:00 and y = 226.145. I have an option that truncates what is displayed on the tick so instead of displaying the entire datetime format, it only displays the hour.
Here is some of my code:
const data = {
labels: Object.keys(stockdata),
datasets: [
{
data: Object.values(stockdata),
borderColor: "rgba(75,192,192,1)",
},
],
};
const options = {
responsive: true,
plugins: {
legend: {
position: "top",
},
title: {
display: true,
text: "Chart.js Line Chart",
},
},
pointRadius: 0,
scales: {
x: {
ticks: {
callback: function (val) {
const time = parseInt(
this.getLabelForValue(val).split(" ")[1].split(":")[0] % 12
);
return time == 0 ? 12 : time;
},
maxTicksLimit: 7,
},
grid: {
color: "#303030",
},
},
y: {
grid: {
color: "#303030",
},
},
},
};
React component render:
<Line data={data} options={options} />
I assume the issue is, that your localtime has a date offset off -1 hours, but without seeing the data (and knowing the offset), I can't say for sure.
If this would be the case, you could/would have to convert your dataset values. Depending on your dataset and available libraries you could use functions like:
momentjs:
let localDate= moment.utc("2023-02-01 10:00:00")
.local()
.format("YYYY-MM-DD HH:mm:ss");
vanilajs:
let localDate = new Date(Date.UTC(2023, 1, 1, 10, 0, 0));
You would have to loop through all the x-values / dates entries, to fix this.
I created a bar chart with some chart options with Highcharts React
https://codesandbox.io/s/highchart-bar-uneven-ticks-c6mi5p
The ticks are not distributed evenly. Is there any way to make them even regardless of their values?
I expect to find an option from Highcharts
You can translate your tick positions into a constant interval, calculate data based on the proportion and show mocked labels/tooltips.
For example:
const tickPositions = [40, 60, 80, 100, 160, 220, 280, 340, 400, 460, 520];
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const processedTickPositions = tickPositions.map((tick, index) => index);
const getProcessedData = (data) => {
const foundTick = tickPositions.find(tick => tick > data);
const prevTickIndex = tickPositions.indexOf(foundTick) - 1;
const prevTick = tickPositions[prevTickIndex];
if (!foundTick) {
return processedTickPositions[0];
}
return prevTickIndex + (data - prevTick) / (foundTick - prevTick);
}
const chartOptions = {
series: [{
...,
data: [{
y: getProcessedData(180),
custom: {
value: 180,
unit: "kg",
label: "label"
}
}]
}],
yAxis: [{
...,
labels: {
formatter: function() {
return tickPositions[this.pos]
}
}
}],
...
};
Highcharts.chart('container', chartOptions);
Live demo: http://jsfiddle.net/BlackLabel/yj7akt29/
API Reference: https://api.highcharts.com/highstock/yAxis.labels.formatter
I am facing some issues with Echarts-Line Charts while trying to render the label data on the X-Axis.
Scenario 1 – Plotting XAxis Labels when only single quarter information is available
Expected Output: Only a single label should appear on XAxis.
Expected Output
Actual Output [Echarts] – Duplicate xAxis labels
Echart Output
I want to have one to one mapping between data and xAxis label.
Scenario 2 – Plotting XAxis labels when there is a huge dataset
Expected Output :- The labels on xAxis has all the quarter information.
Expected Output when dataset is large
Actual Output [Echarts]- Some XAxis labels are skipped automatically by Echarts library, I have tried rotation but it still skips the datapoints.
Actual: xAxis Labels got skipped
I want to force Echart to show all the labels irrespective of the overlapping of values.
Sample Code:
import React from 'react';
import ReactEcharts from 'echarts-for-react';
const LineChart : React.FC = (props) => {
var option2={
title: {
text: ''
},
tooltip: {
trigger: 'item'
},
legend: {
x: 'left',
padding: [0, 0, 0, 40],
data: ['Plot this']
},
// Impacts the grid lines, LRBT are kind of a padding which moves the chart
grid: {
show: true,
left: '3%',
containLabel: true,
borderColor: 'white'
},
xAxis: {
name: "Category",
nameLocation: "middle",
nameTextStyle: {
padding: [10, 0, 0, 0]
},
type: 'time',
boundaryGap: false,
splitNumber: 0,
axisLabel: {
interval:0,
showMinLabel: true,
showMaxLabel:true,
formatter: (function (value:any, index:any) {
const date = new Date(value * 1);
const month = (date.getMonth() + 1);
// to ignore duplicate values
if (!([1,4,7,10].includes(month))){
return null;
}
const quarter = `Q${Math.ceil(month / 3)}`
const year = date.getFullYear()
const xAxisData = `${quarter}-${year}`
return xAxisData
})
// formatter:'Q{Q}-{yyyy}'
}
},
yAxis: {
name: "",
nameLocation: "middle",
nameTextStyle: {
padding: [0, 0, 30, 0]
},
splitArea:{
show:true,
areaStyle:{
color:["white", "#FAFBFC"]
}
},
type: 'value'
},
series: [
{
name: 'Plot This',
type: 'line',
symbol: 'emptyCircle',
color: '#00A3E0',
symbolSize: 10,
lineStyle: {
type: 'solid'
},
emphasis: {
focus: 'series',
blurScope: 'coordinateSystem'
},
data: [
[1506816000000, 509680038.04382974],
[1514764800000, 791155276.2344121],
[1522540800000, 799123227.7082155],
[1530403200000, 802979755.202323],
[1538352000000, 808190497.8038454],
[1546300800000, 948760339.9516863],
[1554076800000, 1042540676.5278728],
[1561939200000, 875160118.2571102],
[1569888000000, 712878628.868768],
[1577836800000, 735685154.726105],
[1585699200000, 820177866.0564957],
[1593561600000, 818982140.8503832],
[1601510400000, 815904376.9750341],
[1609459200000, 836625579.7082175],
[1617235200000, 832549982.9206431],
[1625097600000, 828002503.802811],
[1633046400000, 821488484.2030047],
[1640995200000, 823540791.742887],
[1648771200000, 818621496.9663928],
[1656633600000, 813346336.6927732],
[1664582400000, 808353924.8521348],
[1672531200000, 804944324.4562442],
[1680307200000, 799921655.5844442]
]
},
]
}
return (
<div>
<p> </p>
<ReactEcharts
option = {option2}
/>
</div>
);
}
export default LineChart;
Output of the above code:
XAxis with Missing Quarters
Replace the data of the series with below to get the Scenario 1:
data: [
[1506816000000, 509680038.04382974],
]
Output:
Duplicate Quarters
Thanks in advance.
I want to change the origin of the c3 bar graph from zero to one.All the values must be drawn from one not from zero.For better understanding i have attached an image.
There is no config/easy way to change the origin from (0,0) to something different(0,100).
So the alternate/easy way to do this is by changing the axis tick labels and putting grid lines, and manipulating the data values, as shown below:-
In below example, I have tried to move the origin(x-axis from 0 to 100)
Hope this helps.
var chart = c3.generate({
bindto:'#chart_example',
data: {
columns: [
//['data1', 0, 200, -100, 400, 150, -250, 50, 100, 250] // Actual values
['data1', -100, 100, -200, 300, 50, -350, -50, 0, 150] // actual values -100
],
type: 'bar'
},
axis: {
x: {
type: 'category',
categories: ['cat1', 'cat2', 'cat3', 'cat4', 'cat5', 'cat6', 'cat7', 'cat8', 'cat9'],
show: false,
},
y : {
tick: {
//format: d3.format("$,")
format: function (d) { return "$" + (d+100); }
}
}
},
grid: {
y: {
lines: [
{value: 0, text: ''},
]
}
}
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.5/d3.min.js"></script>
<div id="chart_example"/>
I would like to have an array object instead of the following json format;
[1409558400000, 7.45],[1409562000000, 5.71], [1409565600000, 7.50],
... .;
My purpose is to show all data on the graph based on their hh:mm parameter (which is done in the link already), and I ended up such json array;
[10, 7.45],[09, 5.71], [11, 7.50], ...
But I also would like to keep their timestamp in order to have more information about each data point so that I can provide the timestamp when user clicks on a point.
I simply need to have something like this [10, 7.45,1409562000000] ; hour value, age, and timestamp respectively.
How can I have such data array for flot chart ?
var d = [
[1409558400000, 7.45],
[1409562000000, 5.71],
[1409565600000, 7.50],
[1409569200000, 7.63],
[1409576400000, 3.14],
[1409644800000, 7.45],
[1409648400000, 5.71],
[1409652000000, 7.50],
[1409655600000, 7.63],
[1409662800000, 3.14],
[1409731200000, 7.45],
[1409734800000, 5.71],
[1409738400000, 7.50],
[1409742000000, 7.63],
[1409749200000, 3.14]
];
$.each(d, function (index, datapoint) {
datapoint[0] = (new Date(datapoint[0])).getHours();
});
$.plot("#placeholder", [d], {
series: {
lines: {
show: true
},
points: {
show: true
}
},
grid: {
hoverable: true,
clickable: true,
markings: [{
yaxis: {
from: 0,
to: 4
},
color: "#F2CDEA"
}, {
yaxis: {
from: 4,
to: 7
},
color: "#D7EEE1"
}, {
yaxis: {
from: 7,
to: 12
},
color: "#F2CDEA"
}]
},
xaxis: {
},
yaxis: {
min: 0,
max: 12
}
});
$("#placeholder").bind("plotclick", function(event, pos, item) {
var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2);
if (item) {
//window.location="pagex.html";
alert("x: " + x);
//plot.highlight(item.series, item.datapoint);
}
});
<!-- basic time series flot chart -->
<h>Create a custom green range</h>
<div style="height: 400px; width: 600px;" id="placeholder"></div>
http://jsfiddle.net/shamaleyte/wzLaqzf5/1/
Basically I adapt the answer given in the following link for my scenario.
Link for Referenced answer
Link : displaying custom tooltip when hovering over a point in flot
My Code:
var data = [
[1409558400000, 7.45],
[1409562000033, 5.71],
];
$.each(data, function (index, datapoint) {
datapoint[2] = datapoint[0]; // copy the timestamp and paste it as the 3rd object
datapoint[0] = (new Date(datapoint[0])).getHours(); // to put hours on y axis
});
$.plot("#placeholder", [d2], {
series: {
lines: {
show: true
},
points: {
show: true
}
},
grid: {
hoverable: true,
clickable: true,
markings: [{
yaxis: {
from: 0,
to: 4
},
color: "#F2CDEA"
}, {
yaxis: {
from: 4,
to: 7
},
color: "#D7EEE1"
}, {
yaxis: {
from: 7,
to: 12
},
color: "#F2CDEA"
}]
},
xaxis: {
},
yaxis: {
min: 0,
max: 12
}
});
$("#placeholder").bind("plotclick", function(event, pos, item) {
var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2);
var tooltip = item.series.data[item.dataIndex][2];
if (item) {
//window.location="pagex.html";
alert("x: " + tooltip);
//plot.highlight(item.series, item.datapoint);
}
});
My Fiddle : http://jsfiddle.net/shamaleyte/wzLaqzf5/2/