Chartjs different length of labels and datasets - javascript

How to organize data depending datasets?
// Bar Chart Example
var ctx = document.getElementById("myBarChart");
var myLineChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [ "Mar", "Apr", ],
datasets: [
{
label: "serj",
backgroundColor: "#11564D",
borderColor: "rgba(2,117,216,1)",
data: [{x: "Mar", y: 128400}, {x: "Apr", y: 53500}, ],
},
{
label: "aisha",
backgroundColor: "#508D2F",
borderColor: "rgba(2,117,216,1)",
data: [{x: "Mar", y: 58500}, {x: "Apr", y: 12000}, ],
},
{
label: "serikzhan",
backgroundColor: "#3F22F5",
borderColor: "rgba(2,117,216,1)",
data: [{x: "Apr", y: 8000}, ],
},
],
},
options: {
scales: {
xAxes: [{
time: {
unit: 'month',
},
gridLines: {
display: false
},
ticks: {
maxTicksLimit: 6
}
}],
yAxes: [{
ticks: {
min: 0,
max: 150000,
maxTicksLimit: 5
},
gridLines: {
display: true
}
}],
},
legend: {
display: false
}
}
});
All the datasets and labels created automatically. Problem is all the data begins from March not depending x axes. Different users have different data with different months. Have we way solve the probleme with only chartjs api?

Your approach is almost fine. The only thing that needs to be changed is removing data.labels and defining xAxis as follows:
xAxes: [{
offset: true,
type: 'time',
time: {
parser: 'MMM',
unit: 'month',
displayFormats: {
month: 'MMM'
}
},
Please note that Chart.js uses Moment.js for the functionality of the
time axis. Therefore you should use the bundled version of Chart.js that includes Moment.js in a single file.
var ctx = document.getElementById("myBarChart");
var myLineChart = new Chart(ctx, {
type: 'bar',
data: {
datasets: [
{
label: "serj",
backgroundColor: "#11564D",
borderColor: "rgba(2,117,216,1)",
data: [{x: "Mar", y: 128400}, {x: "Apr", y: 53500}]
},
{
label: "aisha",
backgroundColor: "#508D2F",
borderColor: "rgba(2,117,216,1)",
data: [{x: "Mar", y: 58500}, {x: "Apr", y: 12000}]
},
{
label: "serikzhan",
backgroundColor: "#3F22F5",
borderColor: "rgba(2,117,216,1)",
data: [{x: "Apr", y: 8000}]
}
]
},
options: {
scales: {
xAxes: [{
offset: true,
type: 'time',
time: {
parser: 'MMM',
unit: 'month',
displayFormats: {
month: 'MMM'
}
},
gridLines: {
display: false
},
ticks: {
maxTicksLimit: 6
}
}],
yAxes: [{
ticks: {
min: 0,
max: 150000,
maxTicksLimit: 5
},
gridLines: {
display: true
}
}],
},
legend: {
display: false
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="myBarChart" height="90"></canvas>

Related

Format chart.js x labels

I use chart.js with React. My question is how to show the month label (MMM) only once per month?
The chart currently has labels: [May 15, May 18, May 21, May 24, ...]
As result I want to get: [May 15, 18, 21, 24, 27, 30, Jun 2, 5, ...]
CodeSandbox
Line Chart:
import React from 'react'
import { Line } from 'react-chartjs-2'
import date from 'date-and-time'
const startDate = new Date(2020, 4, 15)
//===fake data===
const json = '{"responses":[{"rows":[{"values":["1"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["1"]},{"values":["6"]},{"values":["7"]},{"values":["5"]},{"values":["8"]},{"values":["9"]},{"values":["2"]},{"values":["1"]},{"values":["1"]},{"values":["1"]},{"values":["6"]},{"values":["3"]},{"values":["0"]},{"values":["20"]},{"values":["9"]},{"values":["3"]},{"values":["2"]},{"values":["1"]},{"values":["13"]},{"values":["3"]},{"values":["13"]},{"values":["13"]},{"values":["7"]},{"values":["12"]},{"values":["0"]}]}]}'
const values = JSON.parse(json).responses[0].rows.map((row, index) => {
let date = new Date(2020, 4, 20)
date.setDate(startDate.getDate() + index)
return {
y: row.values[0],
x: date,
}
})
//===============
const options = {
legend: {
display: false,
},
hover: {
mode: 'index',
intersect: false,
animationDuration: 0,
},
scales: {
yAxes: [{ position: 'right' }],
xAxes: [{
gridLines: { display: false },
distribution: 'linear',
type: 'time',
time: {
parser: 'MMM D',
tooltipFormat: 'MMM D',
unit: 'day',
unitStepSize: 3,
displayFormats: {
day: 'MMM D',
},
},
ticks: {
min: startDate,
max: date.format(date.addDays(new Date(), 1), 'MMM D'),
autoSkip: true
},
}],
},
tooltips: {
mode: 'x-axis',
},
}
const data = {
datasets: [
{
label: 'test',
fill: false,
data: values,
backgroundColor: '#fff',
borderWidth: 2,
lineTension: 0,
borderColor: 'forestgreen',
hoverBorderWidth: 2,
pointBorderColor: 'rgba(0, 0, 0, 0)',
pointBackgroundColor: 'rgba(0, 0, 0, 0)',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'forestgreen',
showLine: true,
}
],
}
const LineChart = () => <Line data={data} options={options}/>
export default LineChart
Solution 1 label filter:
According to the filtering labels sample you can set a function to define what should be displayed:
options: {
scales: {
x: {
display: true,
ticks: {
callback: function(dataLabel, index) {
// Apply logic to remove name of the month
return dataLabel
}
}
},
y: {
display: true,
beginAtZero: false
}
}
}
Github source of the example
Solution 2:
You could prepare your labels array beforehand. Filter the occurence of all the upcoming mentions and feed this array to chart.js.
Define different displayFormats for day and month.
Enable ticks.major.
Mark the desired ticks as major through the afterBuildTicks callback.
time: {
...
displayFormats: {
day: 'D',
month: 'MMM D',
},
},
ticks: {
major: {
enabled: true
}
},
afterBuildTicks: (scale, ticks) => {
ticks.forEach((t, i) => t.major = i == 0 || new Date(t.value).getMonth() != new Date(ticks[i - 1].value).getMonth());
return ticks;
}
Please take a look at your amended code and see how it works.
const startDate = new Date(2020, 4, 15)
//===fake data===
const json = '{"responses":[{"rows":[{"values":["1"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["0"]},{"values":["1"]},{"values":["6"]},{"values":["7"]},{"values":["5"]},{"values":["8"]},{"values":["9"]},{"values":["2"]},{"values":["1"]},{"values":["1"]},{"values":["1"]},{"values":["6"]},{"values":["3"]},{"values":["0"]},{"values":["20"]},{"values":["9"]},{"values":["3"]},{"values":["2"]},{"values":["1"]},{"values":["13"]},{"values":["3"]},{"values":["13"]},{"values":["13"]},{"values":["7"]},{"values":["12"]},{"values":["0"]}]}]}'
const values = JSON.parse(json).responses[0].rows.map((row, index) => {
let date = new Date(2020, 4, 20);
date.setDate(startDate.getDate() + index)
return {
y: row.values[0],
x: date
}
})
//===============
const options = {
legend: {
display: false
},
hover: {
mode: 'index',
intersect: false,
animationDuration: 0
},
scales: {
yAxes: [{
position: 'right'
}],
xAxes: [{
gridLines: {
display: false
},
distribution: 'linear',
type: 'time',
time: {
tooltipFormat: 'MMM D',
unit: 'day',
unitStepSize: 3,
displayFormats: {
day: 'D',
month: 'MMM D',
},
},
ticks: {
major: {
enabled: true
}
},
afterBuildTicks: (scale, ticks) => {
ticks.forEach((t, i) => t.major = i == 0 || new Date(t.value).getMonth() != new Date(ticks[i - 1].value).getMonth());
return ticks;
}
}]
},
tooltips: {
mode: 'x-axis',
}
};
const data = {
datasets: [{
label: 'test',
fill: false,
data: values,
backgroundColor: '#fff',
borderWidth: 2,
lineTension: 0,
borderColor: 'forestgreen',
hoverBorderWidth: 2,
pointBorderColor: 'rgba(0, 0, 0, 0)',
pointBackgroundColor: 'rgba(0, 0, 0, 0)',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'forestgreen',
showLine: true,
}],
};
new Chart('myChart', {
type: 'line',
data: data,
options: options
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="myChart" height="90"></canvas>

Displaying line chart for multiple months using chart.js

I have to display a line chart with two different datasets in one single chart. After execution of the query I got the plan_plan and actual_plan of the following form.
plan_plan = 0: {label: "Feb-20", plan_hrs: "20"}
1: {label: "Oct-20", plan_hrs: "94"}
actual_plan = 0: {label: "Mar-20", actual_hrs: "1"}
javacript code:
function show_Graph()
{
{
var plandata = <?php echo json_encode($plan_plan); ?>;
var actualdata = <?php echo json_encode($actual_plan); ?>;
var labels = [];
for (var i in plandata) {
labels.push(plandata[i].label);
}
for (var j in actualdata) {
labels.push(actualdata[j].label);
}
new Chart("scurve_chart", {
type: 'line',
data: {
labels: Array.from(labels),
datasets: [{
label: "Planned Hours",
fill: false,
borderColor: "rgba(255, 0, 0, 1)",
pointHoverBackgroundColor: "rgba(255, 0, 0, 1)",
data: plandata.map(o => ({ x: Number(o.label), y: Number(o.plan_hrs)}))
},
{
label: "Actual Hours",
fill: false,
backgroundColor: "rgba(0, 255, 0, 0.75)",
borderColor: "rgba(0, 255, 0, 1)",
pointHoverBackgroundColor: "rgba(0, 255, 0, 1)",
pointHoverBorderColor: "rgba(0, 255, 0, 1)",
data: actualdata.map(o => ({x: Number(o.label), y: Number(o.actual_hrs)}))
}
]
},
options: {
tooltips: {
callbacks: {
title: (tooltipItem, data) => "Month " + data.datasets[tooltipItem[0].datasetIndex].data[tooltipItem[0].index].x
}
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
},
scaleLabel: {
display: true,
labelString: 'Hours'
}
}],
xAxes: [{
ticks: {
min: 0,
max: 53,
stepSize: 1
},
scaleLabel: {
display: true,
labelString: 'Month'
}
}]
}
}
});
}}
I want to get the month in the format (Jan-20) in x-axis and then plan_hrs and actual_hrs data in y-axis which can be shown as a line chart. And also should show a single point entry even when there are no data points to be connected. I have used the script tags:
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.js"></script>
But it is not showing graph when I am including the following script for bootstrap:
<script src="build/js/custom.min.js">
I can help for parsing and displaying the dates on the xAxis but unfortunately I don't know Bootstrap.
Define your xAxis as follows:
xAxes: [{
type: 'time',
time: {
parser: 'MMM-YY',
unit: 'month',
displayFormats: {
month: 'MMM-YY'
}
}
}]
Chart.js internally uses Moment.js, hence you can use the following date/time formats for parsing and displaying the date. In your case, this is 'MMM-YYD'.
const plan_plan = [{label: "Feb-20", plan_hrs: "20"}, {label: "Oct-20", plan_hrs: "94"}];
const actual_plan = [{label: "Mar-20", actual_hrs: "1"}];
new Chart("scurve_chart", {
type: 'line',
data: {
datasets: [{
label: "Planned Hours",
fill: false,
borderColor: "rgba(255, 0, 0, 1)",
data: plan_plan.map(o => ({ x: o.label, y: Number(o.plan_hrs)}))
},
{
label: "Actual Hours",
fill: false,
borderColor: "rgba(0, 255, 0, 1)",
data: actual_plan.map(o => ({x: o.label, y: Number(o.actual_hrs)}))
}
]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}],
xAxes: [{
type: 'time',
time: {
parser: 'MMM-YY',
unit: 'month',
displayFormats: {
month: 'MMM-YY'
}
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.js"></script>
<canvas id="scurve_chart" height="90"></canvas>

Change color of X axis values to multi color values - Chart.js

I am using Chart.js (http://www.chartjs.org/docs/) for charting.
My type Chart is Bar.
Label of X axis have 4 lines.
I Change color of X axis values. color of values is one color.
But I want one line per color and color same like the bar color.
var barChartData = {
labels: [["Injection", 10, 20], // here I want to change the color
["Electronics", 5, 15],
["TOTAL", 15, 35]
],
datasets: [{
label: "2018",
backgroundColor: window.chartColors.orange,
yAxisID: 'A',
data: [10, 5, 15]
}, {
label: "2017",
backgroundColor: window.chartColors.green,
yAxisID: 'A',
data: [20, 15, 35]
}]
};
var canvas = document.getElementById('canvas').getContext('2d');
new Chart(canvas, {
type: 'bar',
data: barChartData,
options: {
scales: {
yAxes: [{
id: 'A',
type: 'linear',
position: 'left',
}, {
id: 'B',
type: 'linear',
position: 'right',
ticks: {
max: 100,
min: 0
}
}],
xAxes: [{
ticks: {
fontColor: "#222", // This here that I changed.
},
}]
}
}
})
I want to change color of labels are 10, 5, 15 is orange and 20, 15, 35 is green and Injection, Electronics, TOTAL is black
Can I do that? How?
var myData = [
["id1","test 11111","AA",1.95],
["id2","test 2","BB",1.94],
["id3","test 3","CC",1.93],
["id4","test 4","DD",1.93],
["id5","test 5","EE",1.91],
["id6","test 6","FF",1.90],
["id7","test 7","GG",1.82],
["id8","test 8","HH",1.85],
["id9","test 9","II",1.83],
["id10","test 10","JJ",1.79]
];
var ctx = $("#c");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
datasets: [{
label: '# of Votes',
xAxisID:'modelAxis',
data: myData.map((entry)=>entry[3])
}]
},
options:{
scales:{
xAxes:[
{
id:'modelAxis',
type:"category",
ticks:{
//maxRotation:0,
autoSkip: false,
callback:function(label, x2, x3, x4){
return label;
}
},
labels:myData.map((entry=>entry[1]))
},
{
id:'groupAxis',
type:"category",
gridLines: {
display: false,
drawBorder: false,
drawOnChartArea: false,
offsetGridLines: false
},
ticks:{
padding:0,
maxRotation:0,
fontSize: 10,
fontColor: '#FF9090',
autoSkip: false,
callback:function(label){
return label;
}
},
offset: true,
labels:myData.map((entry=>entry[1]))
},{
id:'groupAxis2',
type:"category",
gridLines: {
display: false,
drawBorder: false,
drawOnChartArea: false,
offsetGridLines: false
},
scaleLabel:{
padding: 10,
},
ticks:{
padding:0,
fontSize: 10,
fontColor: '#AB64F4',
maxRotation:0,
autoSkip: false,
callback:function(label){
return label;
}
},
offset: true,
labels:myData.map((entry=>entry[1]))
}
],
yAxes:[{
ticks:{
beginAtZero:true
}
}]
}
}
});

How to set axes' step size in Chart.js 2?

I created a simple line chart using chart.js with 3 Y axes:
https://codepen.io/anon/pen/dZVgKw
As you can see, the last one is going from 10 to 20 without any number between. How can I set step size here?
This is how I add an axe:
{
id: 'C',
type: 'linear',
position: 'left',
ticks: {
max: 10,
min: 20,
},
}
Thanks.
How can I set step size here?
Straight from the samples (Linear Scale, step size):
By setting a stepSize value.
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Month'
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Value'
},
ticks: {
min: 0,
max: 100,
// forces step size to be 5 units
stepSize: 5 // <----- This prop sets the stepSize
}
}]
}
Here's a live example:
var ctx = document.getElementById('chartJSContainer').getContext('2d')
new Chart(ctx, {
type: 'line',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [
{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1
}
]
},
options: {
scales: {
yAxes: [{
ticks: {
reverse: false,
stepSize: 3
},
}]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.js"></script>
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
</body>
this.data = {
labels: Xaxis,
datasets: [
{
label: "Primary",
data:Primyaxis,
type: 'line',
borderColor:'#eddb1c',
backgroundColor:'#FFF3D6',
fill: false,
pointBorderColor: 'yellow',
pointBackgroundColor: 'yellow',
borderWidth: 1.5
},
{
label: "Secondary",
data: Secyaxis,
type: 'line',
borderColor:'#FF7A96',
backgroundColor:'#EAC3CC',
fill: false,
pointBorderColor: 'red',
pointBackgroundColor: 'red'
}
]
};
this.options = {
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Extra Distance Interval From Origin'
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Percentage of Employees'
},
ticks: {
// min: 50,
max: 100,
// forces step size to be 5 units
stepSize: 2 // <----- This prop sets the stepSize
}
}]
},
pan: {
enabled: true,
},
zoom: {
enabled: true,
},
responsive: true,
}}

How to use two Y axes in Chart.js v2?

I am trying to create a line chart with two datasets, each with its own Y scale / axis (one to the left, one to the right of the graph) using Chart.js.
This is my code (jsfiddle):
var canvas = document.getElementById('chart');
new Chart(canvas, {
type: 'line',
data: {
labels: [ '1', '2', '3', '4', '5' ],
datasets: [
{
label: 'A',
yAxesGroup: 'A',
data: [ 100, 96, 84, 76, 69 ]
},
{
label: 'B',
yAxesGroup: 'B',
data: [ 1, 1, 1, 1, 0 ]
}
]
},
options: {
yAxes: [
{
name: 'A',
type: 'linear',
position: 'left',
scalePositionLeft: true
},
{
name: 'B',
type: 'linear',
position: 'right',
scalePositionLeft: false,
min: 0,
max: 1
}
]
}
});
However, the second axis is not visible and the second dataset is still scaled exactly as the first (0 to 100 instead of 0 to 1). What do I need to change?
For ChartJs 2.x only a couple changes need to be made (it looks like you have tried to combine 2.x options with the multi-axes options from my fork?),
The yAxes field needs to be in a scales object
the yAxis is referenced by id not name.
For the scale steps/size you just need to wrap these options in a ticks object.
No need forscalePositionLeft this is covered by position
Example:
var canvas = document.getElementById('chart');
new Chart(canvas, {
type: 'line',
data: {
labels: ['1', '2', '3', '4', '5'],
datasets: [{
label: 'A',
yAxisID: 'A',
data: [100, 96, 84, 76, 69]
}, {
label: 'B',
yAxisID: 'B',
data: [1, 1, 1, 1, 0]
}]
},
options: {
scales: {
yAxes: [{
id: 'A',
type: 'linear',
position: 'left',
}, {
id: 'B',
type: 'linear',
position: 'right',
ticks: {
max: 1,
min: 0
}
}]
}
}
});
fiddle example
The accepted answer no longer works as of 3.5, and the cause is listed as part of the breaking changes for 3.X (See 3.x Migration Guide)
The updated code below changes the scales property, from scales: {yScales: [...]} to scales: {[id]: {[options]}} , and also adds fill: true, (Was changed at 3.X from defaulting to true) and tension: 0.4 (The example provided before does have smooth curves, and seems like it was an undocumented "breaking" change)
var canvas = document.getElementById('myChart');
new Chart(canvas, {
type: 'line',
data: {
labels: ['1', '2', '3', '4', '5'],
datasets: [{
label: 'A',
yAxisID: 'A',
data: [100, 96, 84, 76, 69],
fill: true,
tension: 0.4
}, {
label: 'B',
yAxisID: 'B',
data: [1, 1, 1, 1, 0],
fill: true,
tension: 0.4
}]
},
options: {
scales: {
A: {
type: 'linear',
position: 'left',
},
B: {
type: 'linear',
position: 'right',
ticks: {
max: 1,
min: 0
}
}
}
}
});
This solution is working in react.
// "chart.js": "^2.9.4"
// "react-chartjs-2": "^2.11.1"
const lineChartData = {
data: {
labels: ['1', '2', '3', '4', '5', '6'],
datasets: [
{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
fill: false,
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgba(255, 99, 132, 0.2)',
},
{
label: '# of Votes',
data: [19, 9, 2, 1, 1, 21],
fill: false,
backgroundColor: 'rgb(122, 99, 255)',
borderColor: 'rgba(102, 99, 255, 0.2)',
}
],
},
options: {
scales: {
yAxes: [
{
type: 'linear',
display: true,
position: 'left',
ticks: {
beginAtZero: true,
},
},
{
type: 'linear',
display: true,
position: 'left',
ticks: {
beginAtZero: true,
},
},
],
},
}
}
<Line
data={lineChartData.data}
options={lineChartData.options}
height={30}
width={80}
options={{ maintainAspectRatio: true }}
/>

Categories