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
When creating a chart, you want to tell the viewer what data they are viewing. To do this, you need to label the axis. Namespace: options.scales [scaleId].title, it defines options for the scale title. Note that this only applies to cartesian axes. If true, display the axis title. Alignment of the axis title.
Formatting labels is very simple by using a culture name, and a format string. By default the culture name 'en-US' indicating US English language is used. However, all cultures are supported. Example: cultures Enum All possible culture names. A format string can be used with an axis to specify the type of values the axis represents.
Number or date values can be formatted without a chart as well by using the JSC.formatDate () and JSC.formatNumber () utility functions. This is useful when using a function with chart label text properties instead of strings. The following references list the supported format strings that can be used with formatString properties:
By using labelFormatter, you can return any value to be displayed on axis. Note If you have to access any preset options of the chart, you can access them via e.chart.options. For example e.chart.options.title.text
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.
displayFormats
for day
and month
.ticks.major
.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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With