Issue
I want the following chart to show the x-axis labels for the 3 specified plotted points (365 Days, 730 Days, and 1095 Days) and hide the rest of the labels for the x-axis but the labels should still show up when you hover over the line as tooltips.
I tried multiple solutions including this callback method but it doesn't work as expected:
scales: {
xAxes: [{
ticks: {
userCallback: function(value, index) {
if (index === 364 || index === 729 || index === 1094)
return this.getLabelForValue(value);
else
return null;
},
autoSkip: false
}
}],
By the way, here's my full code for the line chart, maybe it have to do something with the x-axis labels that I get from an array:
// Reward Over Time Chart Function
var rewardChart = null;
var ctx3 = document.getElementById('rewardOverTimeChart').getContext('2d');
rewardChartCreator(13);
function rewardChartCreator(dailyRewardUSD) {
// Set time period
const days3Years = 365 * 3;
// Calculate the rewards over time
var rewards = [];
for (let day = 1; day <= days3Years; day++) {
rewards.push(dailyRewardUSD * day);
}
if (rewardChart != null) {
rewardChart.destroy(); // DESTROYING OLD CHART BEFORE CREATING NEW ONE
}
// Create the chart
rewardChart = new Chart(ctx3, {
type: 'line',
data: {
labels: Array.from({ length: days3Years }, (_, i) => i === 0 ? '1 Day' : `${i + 1} Days`),
datasets: [{
label: ' Reward',
data: rewards,
borderColor: '#00ABE7', // Blue
backgroundColor: 'rgba(254, 33, 209, 0.2)',
borderWidth: 1,
pointBackgroundColor: rewards.map((_, i) => [364, 729, 1094].includes(i) ? 'white' : '#00ABE7'),
pointRadius: function(context) {
let index = context.dataIndex;
return [364, 729, 1094].includes(index) ? 10 : 1;
},
pointHoverRadius: 4,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
scales: {
xAxes: [{
ticks: {
userCallback: function(value, index) {
if (index === 364 || index === 729 || index === 1094)
return this.getLabelForValue(value);
else
return null;
},
autoSkip: false
}
}],
x: {
display: false,
type: 'category',
position: 'bottom',
},
y: {
title: {
display: false,
text: 'Reward',
font: {
size: 16,
weight: 'bold'
}
},
ticks: {
stepSize: 300,
callback: function(value) {
if (value == 0)
return '$' + 100;
else
return '$' + value;
}
}
}
},
plugins: {
legend: {
display: false,
},
tooltip: {
callbacks: {
label: function(context) {
let label = context.dataset.label || '';
if (label) {
label += ': ';
}
if (context.parsed.y !== null) {
label += new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(context.parsed.y);
}
return label;
}
}
}
},
animation: {
duration: 1000, // Animation duration in milliseconds
easing: 'easeInOutElastic' // Easing function for the animation
},
elements: {
point: {
radius: customRadius,
display: true
}
}
}
});
}
function customRadius(context) {
let index = context.dataIndex;
let value = context.dataset.data[index];
return index = 364 || index == 729 || index == 1094 ? 10 : 2;
}
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.0.0/dist/chart.min.js"></script>
<canvas id="rewardOverTimeChart"></canvas>
Solution
Finally solved it by removing xAxes and adding autoSkip: false
and the following callback
function to the x-axis ticks.
- Renamed
options.scales.xAxes
(array) tooptions.scales.x
(object) - Added
options.scales.x.grid.display=false
- Added
options.scales.x.display=true
- Added
options.scales.x.type='category'
- Added
options.scales.x.position='bottom'
- Added
options.scales.ticks.autoSkip=false
- Moved
options.scales.ticks.userCallback
tooptions.scales.ticks.callback
- Changed callback to return
''
instead ofnull
in theelse
block
Here's the complete functional code:
// Reward Over Time Chart Function
var rewardChart = null;
var ctx3 = document.getElementById('rewardOverTimeChart').getContext('2d');
rewardChartCreator(13);
function rewardChartCreator(dailyRewardUSD) {
// Set time period
const days3Years = 365 * 3;
// Calculate the rewards over time
var rewards = [];
for (let day = 1; day <= days3Years; day++) {
rewards.push(dailyRewardUSD * day);
}
if (rewardChart != null) {
rewardChart.destroy(); // DESTROYING OLD CHART BEFORE CREATING NEW ONE
}
// Create the chart
rewardChart = new Chart(ctx3, {
type: 'line',
data: {
labels: Array.from({ length: days3Years }, (_, i) => i === 0 ? '1 Day' : `${i + 1} Days`),
datasets: [{
label: ' Reward',
data: rewards,
borderColor: '#00ABE7', // Blue
backgroundColor: 'rgba(254, 33, 209, 0.2)',
borderWidth: 1,
pointBackgroundColor: rewards.map((_, i) => [364, 729, 1094].includes(i) ? 'white' : '#00ABE7'),
pointRadius: function(context) {
let index = context.dataIndex;
return [364, 729, 1094].includes(index) ? 10 : 1;
},
pointHoverRadius: 4,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
scales: {
x: {
grid: {
display: false
},
display: true,
type: 'category',
position: 'bottom',
ticks: {
autoSkip: false,
callback: function(value, index) {
if (index === 364 || index === 729 || index === 1094)
return this.getLabelForValue(value);
else
return '';
},
}
},
y: {
title: {
display: false,
text: 'Reward',
font: {
size: 16,
weight: 'bold'
}
},
ticks: {
stepSize: 300,
callback: function(value) {
if (value == 0)
return '$' + 100;
else
return '$' + value;
}
}
}
},
plugins: {
legend: {
display: false,
},
tooltip: {
callbacks: {
label: function(context) {
let label = context.dataset.label || '';
if (label) {
label += ': ';
}
if (context.parsed.y !== null) {
label += new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(context.parsed.y);
}
return label;
}
}
}
},
animation: {
duration: 1000, // Animation duration in milliseconds
easing: 'easeInOutElastic' // Easing function for the animation
},
elements: {
point: {
radius: customRadius,
display: true
}
}
}
});
}
function customRadius(context) {
let index = context.dataIndex;
let value = context.dataset.data[index];
return index = 364 || index == 729 || index == 1094 ? 10 : 2;
}
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.0.0/dist/chart.min.js"></script>
<canvas id="rewardOverTimeChart"></canvas>
Answered By - Aimal
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.