-1π
To make the cursor a pointer while hovering over a label, you can try to assign a CSS cursor value to event.native.target.style.cursor
when hover is triggered.
event.native.target.style.cursor = 'pointer';
To make the label a different color while it is being hovered on, you can try this
myChart.config.options.scales.y.ticks.color = hoverColors; // ['black','red','black'], ['black','black','red'], ['red','black','black']
UPDATE
Thanks to LeeLenalee for giving an almost correct answer. Iβve edited the code above so it fits what is required in the problem. Donβt forget to change source of the library in the HTML from :
https://cdn.jsdelivr.net/npm/chart.js@4.2.0
to :
https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.js
Updated code:
window.onload = function() {
const findLabel = (labels, evt) => {
let found = false;
let res = null;
try {
labels.forEach(l => {
l.labels.forEach((label, index) => {
if (evt.x > label.x && evt.x < label.x2 && evt.y > label.y && evt.y < label.y2) {
res = {
label: label.label,
index
};
found = true;
}
});
});
} catch (e) {}
return [found, res];
};
const getLabelHitboxes = (scales) => {
try {
return Object.values(scales).map((s) => ({
scaleId: s.id,
labels: s._labelItems.map((e, i) => ({
x: e.translation[0] - s._labelSizes.widths[i],
x2: e.translation[0] + s._labelSizes.widths[i] / 2,
y: e.translation[1] - s._labelSizes.heights[i] / 2,
y2: e.translation[1] + s._labelSizes.heights[i] / 2,
label: e.label,
index: i
}))
}));
} catch (e) {}
};
const changeCursorAndLabelColor = (event, chart, index, hoverMode) => {
// your hover color here
// const hoverColor = '#ff0000';
const hoverColor = 'red';
const hoverColors = [];
for (let i = 0; i < myChart.data.datasets[0].data.length; i++) {
if (hoverMode) {
// change cursor
event.native.target.style.cursor = 'pointer';
if (index === i) {
hoverColors.push(hoverColor);
} else {
hoverColors.push(defaultLabelColor);
}
} else {
// change cursor
event.native.target.style.cursor = 'default';
hoverColors.push(defaultLabelColor);
}
}
// change label to your hover color
myChart.config.options.scales.y.ticks.color = hoverColors;
// update chart when hover is triggered
myChart.update();
}
let foundMode = false;
const plugin = {
id: 'customHover',
afterEvent: (chart, event, opts) => {
const evt = event.event;
if (evt.type !== 'mousemove') {
return;
}
const [found, labelInfo] = findLabel(getLabelHitboxes(chart.scales), evt);
if (found && myChart.data.labels.includes(labelInfo.label)) {
changeCursorAndLabelColor(evt, chart, labelInfo.index, true);
foundMode = true;
} else {
if (foundMode) changeCursorAndLabelColor(evt, chart, null, false);
foundMode = false;
}
}
}
Chart.register(plugin);
var ctx = document.getElementById('myChart');
const myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Item A', 'Item B', 'Item C'],
datasets: [{
label: 'My Data',
data: [1, 2, 3],
backgroundColor: 'lightblue'
}]
},
options: {
responsive: true,
indexAxis: 'y',
plugins: {
legend: {
display: false
},
tooltip: {
enabled: false
},
},
onHover: (event, chart) => {
if (foundMode) changeCursorAndLabelColor(event, chart, null, false);
foundMode = false;
}
}
});
const defaultLabelColor = myChart.config.options.scales.y.ticks.color;
};
.chart-container {
position: relative;
height: 90vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.js"></script>
<div class="chart-container">
<canvas id="myChart"></canvas>
</div>
0π
You can just use the custom plugin from that question and ignore everything but mousemove events instead of ignoring everything but click events:
const findLabel = (labels, evt) => {
let found = false;
let res = null;
labels.forEach(l => {
l.labels.forEach((label, index) => {
if (evt.x > label.x && evt.x < label.x2 && evt.y > label.y && evt.y < label.y2) {
res = {
label: label.label,
index
};
found = true;
}
});
});
return [found, res];
};
const getLabelHitboxes = (scales) => (Object.values(scales).map((s) => ({
scaleId: s.id,
labels: s._labelItems.map((e, i) => ({
x: e.translation[0] - s._labelSizes.widths[i],
x2: e.translation[0] + s._labelSizes.widths[i] / 2,
y: e.translation[1] - s._labelSizes.heights[i] / 2,
y2: e.translation[1] + s._labelSizes.heights[i] / 2,
label: e.label,
index: i
}))
})));
const plugin = {
id: 'customHover',
afterEvent: (chart, event, opts) => {
const evt = event.event;
if (evt.type !== 'mousemove') {
return;
}
const [found, labelInfo] = findLabel(getLabelHitboxes(chart.scales), evt);
if (found) {
console.log(labelInfo);
}
}
}
Chart.register(plugin);
const options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'pink'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderColor: 'orange'
}
]
},
options: {}
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.js"></script>
</body>
0π
To change the cursor to a pointer when hovering over a category label in a Chart.js bar chart, you can add:
options: {
plugins: {
tooltip: {
mode: 'index',
intersect: false
},
},
interaction: {
mode: 'index',
intersect: false
},
onHover: function(evt, elements) {
if (elements.length) {
document.getElementById("myChart").style.cursor = "pointer";
} else {
document.getElementById("myChart").style.cursor = "default";
}
},
// ...
}
To change the color of a label when it is being hovered on, you can add:
options: {
plugins: {
tooltip: {
mode: 'index',
intersect: false
},
},
interaction: {
mode: 'index',
intersect: false
},
onHover: function(evt, elements) {
if (elements.length) {
var chart = evt.chart;
var datasetIndex = elements[0].datasetIndex;
var index = elements[0].index;
chart.data.labels[index] = '<span style="color: red;">' + chart.data.labels[index] + '</span>';
chart.update();
} else {
var chart = evt.chart;
chart.data.labels = ['Item A', 'Item B', 'Item C'];
chart.update();
}
},
// ...
}