I have a lists of utc timestamps, ready to parse into ChartJS 2.9.3, the graph couldn't show the x-axis time and data is not showing.
Config
let chartConfig = {
type: "line",
data: {
labels: [],
datasets: [
{
pointRadius: 0,
data: [],
backgroundColor: ['rgba(255, 99, 132, 0.2)'],
borderColor: ['rgba(255,99,132,1)'],
borderWidth: 1
}
]
},
options: {
responsive: true,
animation: {
duration: 0
},
hover: {
animationDuration: 0
},
responsiveAnimationDuration: 0,
legend: {
display: false
},
scales: {
xAxes: [{
type: 'time',
ticks: {
source: "data",
autoSkip: true,
maxTicksLimit: 20
},
time: {
parser: 'HH:mm:ss',
tooltipFormat: 'HH:mm:ss',
unit: 'minute',
unitStepSize: 5,
displayFormats: {
'second': 'ss A',
'minute': 'hh:mm A',
'hour': 'HH:mm A'
}
}
}],
yAxes: [{
ticks: {min: 0, max: 150, stepSize: 10 }
}]
}
}
}
Labels (x-axis)
Generates through moment(timestamp).format("HH:mm:ss")
["22:02:30","22:03:00","22:03:30","22:4:00","22:05:00".,"22:07:00","22:10:00"]
Data (y-axis)
[60,78,89,100,120,45,55]
Problem
I took your code and everything works as expected as you can see below. The only thing I had to correct was removing a superfluous dot in the labels array.
new Chart('myChart', {
type: "line",
data: {
labels: ["22:02:30", "22:03:00", "22:03:30", "22:4:00", "22:05:00", "22:07:00", "22:10:00"],
datasets: [{
pointRadius: 0,
data: [60, 78, 89, 100, 120, 45, 55],
backgroundColor: ['rgba(255, 99, 132, 0.2)'],
borderColor: ['rgba(255,99,132,1)'],
borderWidth: 1
}]
},
options: {
responsive: true,
animation: {
duration: 0
},
hover: {
animationDuration: 0
},
responsiveAnimationDuration: 0,
legend: {
display: false
},
scales: {
xAxes: [{
type: 'time',
ticks: {
source: "data",
autoSkip: true,
maxTicksLimit: 20,
minRotation: 30
},
time: {
parser: 'HH:mm:ss',
tooltipFormat: 'HH:mm:ss',
unit: 'minute',
unitStepSize: 5,
displayFormats: {
'minute': 'hh:mm:ss A'
}
}
}],
yAxes: [{
ticks: {
min: 0,
max: 150,
stepSize: 10
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="myChart"></canvas>
Related
Is below chart possible in highchart
Column with high, low and target
Color gradient with denser on target and lighter away
Data table for low, high and target
Managed to get some bits, but not full functionality
https://jsfiddle.net/z9u5hgod/2/
TIA
[
{
type: 'bullet',
dataLabels: [
{ format: '{point.y}' } ,
{format: '{point.target}',
inside: true},
{
inside: true,
verticalAlign: 'bottom',
align: 'center',
format: '{point.low}'
}
],
data: [
{
low: 250,
y: 1650,
target: 750,
color: {
linearGradient: [0, '70%', 0, '50%'],
stops: [
[0, 'green'],
[1, 'orange']
]
}
},
{
low: 100,
y: 2000,
target: 1500
}
]
},
{
data: [{
low: 600,
y: 2350,
target: 2100
}, {
low: 450,
y: 1700,
target: 1250
}]
}]
Response from higcharts developer
https://jsfiddle.net/BlackLabel/xbvp8he7/
const chart = Highcharts.chart('container', {
chart: {
type: 'bullet',
events: {
load() {
const firstSeries = this.series[0];
firstSeries.data.forEach(point => {
const {
low,
y,
target
} = point,
gradientPoint = (y - target) / (y - low);
point.update({
color: {
linearGradient: {
x1: 0,
x2: 0,
y1: 0,
y2: 1
},
stops: [
[0, 'blue'],
[gradientPoint, 'purple'],
[1, 'blue']
],
}
})
})
}
}
},
plotOptions: {
series: {
pointPadding: 0.2,
groupPadding: 0.1,
targetOptions: {
borderWidth: 0,
height: 3,
color: 'red',
width: '100%'
}
}
},
xAxis: {
categories: ['Alex ar', 'Cairo ar']
},
series: [
{
type: 'bullet',
dataLabels: [{
enabled: true,
}, {
enabled: true,
verticalAlign: 'top',
align: 'center',
color: 'white',
useHTML: true,
formatter() {
const point = this.point,
target = point.targetGraphic,
targetY = target.getBBox().y - point.shapeArgs.y - 25;
return `
<div class="datalabelInside" style="position: relative; top: ${targetY}px">${point.target}</div>
`;
}
}, {
verticalAlign: 'bottom',
inside: true,
y: 20,
format: '{point.low}',
enabled: true
}, ],
data: [{
low: 250,
y: 1650,
target: 750
},
{
low: 100,
y: 2000,
target: 1500
}
]
},
{
data: [{
low: 600,
y: 2350,
target: 2100
}, {
low: 450,
y: 1700,
target: 1250
}]
}
],
tooltip: {
pointFormat: '<b>{point.y}</b> (with target at {point.target})'
}
});
Expected:
enter image description here
Current:
enter image description here
I want to have stepsizes and gridlines in the same line and some padding
How can i achieve that with chart.js v3
scales: {
y: {
stacked: true,
grid: {
offset: true,
display: true,
drawBorder: false,
drawOnChartArea: true,
borderDashOffset: 25,
borderColor: "#d1d2db",
borderWidth: 0.8800000000000001,
color: "#d1d2db",
},
min: 0,
max: max,
ticks: {
// forces step size to be 25 units
stepSize: 25,
beginAtZero: true,
callback: callback,
max: max,
},
title: {
display: false,
text: "Y axis title",
},
},
x: {
grid: {
offset: true,
display: true,
drawBorder: false,
drawOnChartArea: false,
drawTicks: false,
tickLength: 0,
// borderDash: [0, 1],
// borderDashOffset: 0,
borderColor: "#d1d2db",
// borderWidth: 0.8800000000000001,
color: "#d1d2db",
},
},
},
Btw, is it also possible to have perpendiculars from data points to x-axis as shown in expected design ?
To have the horizontal grid lines aligned with the y labels, define options.scales.y.grid.offset: false or omit the option.
For the vertical lines from the bottom of the chart up to individual data points, you can use the Plugin Core API. In the afterDraw hook for example, you can draw the lines directly on the canvas using the CanvasRenderingContext2D.
Please take a look at your amended and runnable code and see how it works.
new Chart('chart', {
type: 'line',
plugins: [{
afterDraw: chart => {
var ctx = chart.ctx;
ctx.save();
var xAxis = chart.scales.x;
var yAxis = chart.scales.y;
const data = chart.data.datasets[0].data;
xAxis.ticks.forEach((v, i) => {
var x = xAxis.getPixelForTick(i);
var yTop = yAxis.getPixelForValue(data[i]);
ctx.strokeStyle = '#aaaaaa';
ctx.beginPath();
ctx.moveTo(x, yAxis.bottom);
ctx.lineTo(x, yTop);
ctx.stroke();
});
ctx.restore();
}
}],
data: {
labels: [1, 2, 3, 4, 5, 6, 7],
datasets: [{
label: 'My Data',
data: [65, 59, 80, 81, 56, 55, 68],
borderColor: '#0a0'
}]
},
options: {
scales: {
y: {
stacked: true,
grid: {
display: true,
drawBorder: false,
drawOnChartArea: true,
borderDashOffset: 25,
borderColor: "#d1d2db",
borderWidth: 0.8800000000000001,
color: "#d1d2db",
},
min: 0,
ticks: {
stepSize: 25,
beginAtZero: true,
},
title: {
display: false,
text: "Y axis title",
},
},
x: {
grid: {
offset: true,
display: true,
drawBorder: false,
drawOnChartArea: false,
drawTicks: false,
tickLength: 0,
borderColor: "#d1d2db",
color: "#d1d2db",
},
},
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.min.js"></script>
<canvas id="chart" width="400" height="95"></canvas>
I want to make a chart with min and max vertical lines and bars between them. I can't find information how to set bars' X coordinate or make custom line plot with vertical 'bars' instead of points.
And also I don't understand how to scale X axis, why MAX is left-side MIN? Min=22.5, Max=24.5
let plot_options = {
showScale: true,
pointDot: true,
showLines: true,
maintainAspectRatio: false,
annotation: {
annotations: [
{
type: 'line',
mode: 'vertical',
scaleID: 'y-axis-0',
value: min,
borderColor: 'red',
borderWidth: 2,
label: {
backgroundColor: 'red',
content: 'Min',
enabled: true,
},
},
{
type: 'line',
mode: 'vertical',
scaleID: 'y-axis-0',
value: max,
borderColor: 'red',
borderWidth: 2,
label: {
backgroundColor: 'red',
content: 'MAX',
enabled: true,
},
},
]
},
title: {
display: true,
text: plotHeader,
},
responsive: true,
legend: {
display: false,
},
scales: {
xAxes: [{
scaleLabel: {
display: true,
labelString: labelx
},
ticks: {
min: min,
max: max
}
}],
yAxes: [{
scaleLabel: {
display: true,
labelString: labely
},
ticks: {
beginAtZero: true,
},
}]
},
}
data = {
barPercentage: 0.5,
barThickness: 6,
maxBarThickness: 8,
minBarLength: 2,
labels: labels,
datasets: [{
data: values,
borderColor: BLUE,
backgroundColor: BLUE
}]
}
<Bar options={plot_options} data={data} plugins={ChartAnnotation} />
That's what I expect:
This solution is based on this answer for the positioning of the bars on a linear x-axis.
You can further use the Plugin Core API to draw the vertical min and max lines with their labels directly on the canvas. The API offers a number of hooks that can be used to perform custom code. In your case, you could use the afterDraw hook together with CanvasRenderingContext2D.
Please take a look at the runnable code below and see how it works. It should not be too hard to make similar code work with react-chartjs-2.
new Chart("chart", {
type: 'bar',
plugins: [{
afterDraw: chart => {
let ctx = chart.chart.ctx;
ctx.save();
let xAxis = chart.scales['x-axis-0'];
let yAxis = chart.scales['y-axis-0'];
let dataset = chart.data.datasets[0];
[dataset.min, dataset.max].forEach((v, i) => {
var x = xAxis.getPixelForValue(+v * 1000);
ctx.fillStyle = 'red';
ctx.font = '14px Arial';
ctx.textAlign = 'center';
ctx.fillText(i == 0 ? 'Min' : 'Max', x, yAxis.top + 14);
ctx.fillStyle = 'gray';
ctx.font = '12px Arial';
ctx.fillText(v, x, yAxis.bottom + 20);
ctx.beginPath();
ctx.moveTo(x, yAxis.top + 20);
ctx.strokeStyle = 'red';
ctx.lineTo(x, yAxis.bottom + 3);
ctx.stroke();
});
ctx.restore();
}
}],
data: {
datasets: [{
min: 22.5,
max: 24.5,
data: [
{ x: '22.83', y: 18 },
{ x: '23.17', y: 15 },
{ x: '23.44', y: 13 },
{ x: '24.32', y: 20 }
],
borderColor: 'blue',
backgroundColor: 'blue',
barThickness: 20
}]
},
options: {
legend: {
display: false,
},
scales: {
xAxes: [{
offset: true,
type: 'time',
time: {
parser: 'X',
unit: 'millisecond',
displayFormats: {
millisecond: 'X'
}
},
ticks: {
source: 'data',
min: '22.5',
callback: (v, i, values) => values[i].value / 1000
},
gridLines: {
display: false
},
}],
yAxes: [{
ticks: {
beginAtZero: true,
max: 22,
stepSize: 2
}
}]
}
}
});
canvas {
max-width: 500px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.min.js"></script>
<canvas id="chart" height="200"></canvas>
Hell, all,
I would like to draw the chart like this:
Currently, I can use afterBuildTicks to get only zero yAxis. But the problem is that the whole other ticks were removed also. So Not sure if we have a way to draw zero tick and keep other ticks hidden except the label.
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ['Value 1', 'Value 2', 'Value 3', 'Value 4'],
datasets: [{
label: "Dataset",
data: [20, 15, 27, 18],
backgroundColor: 'rgba(54, 162, 235,0.5)',
}],
},
options: {
responsive: true,
elements: {
line: {
fill: false
}
},
scales: {
xAxes: [
{
position: 'top',
display: true,
gridLines: {
display: true,
},
stacked: true,
ticks: {
fontColor: "#C4C4C4",
fontSize: 10,
}
}
],
yAxes: [
{
type: 'linear',
display: true,
position: 'right',
id: 'y-axis-1',
gridLines: {
display: true,
},
labels: {
show: true
},
stacked: false,
ticks: {
fontColor: "#C4C4C4",
fontSize: 10,
precision: 0,
suggestedMax: 100,
suggestedMin: -100
},
afterBuildTicks:function (axis) {
axis.ticks = [0]
}
}
]
},
tooltips: {
mode: 'label',
bodySpacing: 10,
titleMarginBottom: 10,
titleFontSize: 14,
titleFontStyle: 'bold',
footerAlign: 'right',
callbacks: {
label: (tooltipItem, data) => {
const label = data.datasets[tooltipItem.datasetIndex].label || ''
const value = tooltipItem.value
return ` ${label}: ${value}`
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<canvas id="myChart" height="100"></canvas>
Thanks so much
I found the solution that use: gridLines options to draw chart with width is zero:
gridLines: {
display: true,
tickMarkLength: 10,
lineWidth: 0
}
I'm trying to create an multiline graph using chartjs.
On x-Axis I have dates and on y-Axis i have some amount in integers.
I have two lines, one of them for user's expenses and other for income.
For income I have data of only 2 dates but having difference of month. My second income point on the graph is not on the correct date, it comes on the next date of expenses.
My data looks like this :
[
{ date: '2020-02-24', type: 'income', amount: 900 },
{ date: '2020-03-20', type: 'expense', amount: 100 },
{ date: '2020-03-20', type: 'expense', amount: 830 },
{ date: '2020-03-21', type: 'expense', amount: 50 },
{ date: '2020-03-22', type: 'expense', amount: 560 },
{ date: '2020-03-24', type: 'expense', amount: 600 }
]
In labels dates of income are 2020-02-24 and 2020-03-24 and
rest of the dates are of expenses
Here is my dataset :
{
labels:[ "2020-02-24", "2020-03-20", "2020-03-20", "2020-03-21", "2020-03-22", "2020-03-24" ],
datasets: [
{
label: 'Expenses',
fill: false,
lineTension: 0.5,
backgroundColor: 'rgba(75,192,192,1)',
borderColor: 'rgba(0,0,0,1)',
borderWidth: 2,
data: [ 100, 830, 50, 560 ],
},
{
label: 'Income',
fill: false,
lineTension: 0.5,
backgroundColor: 'blue',
borderColor: 'red',
borderWidth: 2,
data: [ 900, 600 ],
}
]
};
You must not define data.labels, because they are considered for both datasets. Instead, you should define each data point individually using an object containing x and y properties.
data: [
{ x: '2020-02-24', y: 900 },
{ x: '2020-03-24', y: 600 }
]
In the following runnable code snippet, I build such data of individual datasets out of your base data array using filter() and map().
const data = [
{ date: '2020-02-24', type: 'income', amount: 900 },
{ date: '2020-03-15', type: 'expense', amount: 100 },
{ date: '2020-03-20', type: 'expense', amount: 830 },
{ date: '2020-03-25', type: 'expense', amount: 50 },
{ date: '2020-03-28', type: 'expense', amount: 560 },
{ date: '2020-03-24', type: 'income', amount: 600 }
];
var worldChart = new Chart(document.getElementById('myChart'), {
type: 'line',
data: {
datasets: [
{
label: 'Expenses',
fill: false,
lineTension: 0.5,
backgroundColor: 'rgba(75,192,192,1)',
borderColor: 'rgba(0,0,0,1)',
borderWidth: 2,
data: data.filter(o => o.type == 'expense').map(o => ({ x: o.date, y: o.amount }))
},
{
label: 'Income',
fill: false,
lineTension: 0.5,
backgroundColor: 'blue',
borderColor: 'red',
borderWidth: 2,
data: data.filter(o => o.type == 'income').map(o => ({ x: o.date, y: o.amount }))
}
]
},
options: {
responsive: true,
title: {
display: false
},
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'day',
tooltipFormat: 'MMM DD'
}
}],
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="myChart" height="80"></canvas>
const options = {
responsive: true,
maintainAspectRatio: false,
scales: {
y: { title: { display: false, }, ticks: { color: "black", }, },
x: { ticks: { color: "black", autoSkip: true, }, grid: { display: false, } },
},
plugins: { legend: { display: false, }, title: { display: false, }, tooltip: { mode: "index", intersect: false, }, },
hover: { mode: "nearest", intersect: false, },
};
const data={{
labels: chartData?.labels,
datasets: [{ label: "Orders", type: "bar", barThickness: 12, borderRadius: 20, data: chartData?.data, backgroundColor: "#fb6340", },],
}}