Charjs: How to hide other lines on hover? - javascript

I am using Chart.js v3, below is the code but it is not hiding. The goal is that when I hover over a line, it hides other lines and their labels. The code is given below:
<html>
<head>
<script src="https://code.jquery.com/jquery-3.6.3.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment#^2"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.1/chart.min.js"></script>
</head>
<body>
<canvas id="myChart" width="300" height="200"></canvas>
<script>
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, {
type: "line",
data: {
labels: [1, 2, 3, 4, 5],
datasets: [{
label: "Line 1",
data: [1, 2, 3, 4, 5],
borderColor: "red",
backgroundColor: "rgba(255,0,0,0.2)"
}, {
label: "Line 2",
data: [5, 4, 3, 2, 1],
borderColor: "blue",
backgroundColor: "rgba(0,0,255,0.2)"
}, {
label: "Line 3",
data: [2, 4, 6, 8, 10],
borderColor: "green",
backgroundColor: "rgba(0,255,0,0.2)"
}]
},
options: {
hover: {
mode: "index",
intersect: true
},
animation: {
duration: 0
}
}
});
</script>
</body>
</html>

I think you should implement onHover hook in the chart options. Based on hovered element you can hide the others.
2 points of attention I guess:
hover mode should 'point' and not 'index' otherwise all datasets will be hidden
to have a consistent view on chart, you should set min and max on y scale.
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, {
type: "line",
data: {
labels: [1, 2, 3, 4, 5],
datasets: [{
label: "Line 1",
data: [1, 2, 3, 4, 5],
borderColor: "red",
backgroundColor: "rgba(255,0,0,0.2)"
}, {
label: "Line 2",
data: [5, 4, 3, 2, 1],
borderColor: "blue",
backgroundColor: "rgba(0,0,255,0.2)"
}, {
label: "Line 3",
data: [2, 4, 6, 8, 10],
borderColor: "green",
backgroundColor: "rgba(0,255,0,0.2)"
}]
},
options: {
scales: {
y: {
beginAtZero: true,
max: 10
}
},
onHover(e, elements, chart) {
if (elements.length) {
for (const el of elements) {
const dsCount = chart.data.datasets.length;
for (let i = 0; i < dsCount; i++) {
if (i !== el.datasetIndex) {
chart.setDatasetVisibility(i, false);
}
}
}
chart.update();
} else {
const dsCount = chart.data.datasets.length;
for (let i = 0; i < dsCount; i++) {
chart.setDatasetVisibility(i, true);
}
chart.update();
}
},
hover: {
mode: "point",
intersect: true
},
animation: {
duration: 0
}
}
});
.myChartDiv {
max-width: 600px;
max-height: 400px;
}
<html>
<head>
<script src="https://code.jquery.com/jquery-3.6.3.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment#^2"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.1/chart.min.js"></script>
</head>
<body>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"/>
</div>
</body>
</html>

Related

Chartjs adding data values on the right legend

considering the following example:
$(document).ready(function() {
var ctx = document.getElementById('mycanvas').getContext('2d');
var chart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ["CL", "ML", "Spl.L", "PD", "Other Permissions"],
datasets: [{
label: "My First dataset",
backgroundColor: ['#F0CB8C', '#EE97A1', '#A9D5D4', '#E8A3D7', '#CFA3FD'],
data: [7, 3, 3, 4, 8],
}]
},
options: {
legend: {
position: 'right'
}
}
});
})
example
is there a way to have the data on the right of the single label?
like here:
You can add custom labels as advised by #LeeLenalee's solution
and here is your workin code :
$(document).ready(function() {
var ctx = document.getElementById('mycanvas').getContext('2d');
var chart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ["CL", "ML", "Spl.L", "PD", "Other Permissions"],
datasets: [{
label: "My First dataset",
backgroundColor: ['#F0CB8C', '#EE97A1', '#A9D5D4', '#E8A3D7', '#CFA3FD'],
data: [7, 3, 3, 4, 8],
}]
},
options: {
legend: {
labels: {
generateLabels: (chart) => {
const datasets = chart.data.datasets;
return datasets[0].data.map((data, i) => ({
text: `${chart.data.labels[i]} ${data}`,
fillStyle: datasets[0].backgroundColor[i],
}))}
}
}
}
});
})
.chart-container {
width: 280px;
height: 280px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>
<div class="chart-container">
<canvas id="mycanvas"></canvas>
</div>

How could I put a string for the points on the x-axis?

I am using ChartJS v.2, and I would like to label arrayX by a string that will appear when the mouse will be on hover displaying the coordinates.
ArrayX being points (numbers) I should label with something.
data = {
labels: arrayX,
datasets: [{
label: 'ArrayY',
data: arrayY,
fill: false,
borderColor: 'rgb(75, 192, 192)',
tension: 0.1
}]
};
You can use the title callback for this:
var options = {
type: 'line',
data: {
labels: ["10", "15", "30", "80", "5000", "999999"],
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: {
tooltips: {
callbacks: {
title: (a) => ('Test string: ' + a[0].label)
}
}
}
}
var 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/2.9.4/Chart.js"></script>
</body>
I solved using this way, more easy.
options: {
tooltips: {
callbacks: {
title:function(tooltipItems, data){
return 'Y: ' + tooltipItems[0].xLabel;
}
}
}
}

ChatJS 2.8.0 min/max axis issue and labels on the top

I'm using ChartJS 2.8.0 and I have the code below:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
</head>
<body>
<div class="reportGraph">
<canvas id="chartJSContainer"></canvas>
</div>
<script>
const labels = ["stable","happy","composed","certainty","active","aggressive",["responsible","causativ"],["correct","estimation"],"appreciative",["communication","level"]];
const labels2 = [["unstable,","dispersed"],"depressed","nervous","uncertainty","inactiv","inhibited","irresponsible","critical",["lack","of","accord"],"withdrawn"];
const data = {
labels: labels,
datasets: [
{
label: "",
data: [-92, -100, -99, -86, 8, 56, -94, -89, -92, -24],
borderColor: "black",
backgroundColor: "transparent",
type: "line",
borderWidth: 2,
order: 0,
lineTension: 0,
fill: false
},
{
label: "Urgently needs attention",
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
borderColor: "rgb(221, 221, 221)",
backgroundColor: "rgb(221, 221, 221)",
order: 2
},
{
label: "Requires attention",
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
borderColor: "rgb(136, 136, 136)",
backgroundColor: "rgb(136, 136, 136)",
order: 1
},
{
label: "Acceptable under perfect condition",
data: [0, 0, 0, 0, 0, , 0, 0, 0, 0],
borderColor: "rgb(228, 185, 192)",
backgroundColor: "rgb(228, 185, 192)",
order: 3,
type: "bar"
}
]
};
const config = {
type: "bar",
data: data,
options: {
responsive: true,
legend: {
display: true,
position: 'right',
labels: {
fontColor: 'black',
filter: function(item, chart) {
return item.datasetIndex !== 0;
}
}
},
},
scales: {
y: {
ticks: {
suggestedMin: -100,
suggestedMax: 100
}
},
x: {
position: "bottom",
grid: {
offset: true
}
},
x2: {
position: "top",
grid: {
offset: true
},
labels: labels2
}
}
};
var chart = new Chart(document.getElementById("chartJSContainer"), config);
</script>
</body>
</html>
I am unable to have the Y axis to start from -100 to 100 even though I added a code for it.
Also, I want to have the same X-axis labels displayed on the top of the graph too. Any help on the issues I have on this code please? Thanks.
Note: Please do not change the library version 2.8.0 when you suggest a code.
You are using V3 syntax for the scales, version 2 used a different syntax, please look at this link for the documentation for the version you are using
Live example with scale min-max:
var options = {
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: {
min: 0,
max: 100
}
}],
xAxes: [{offset: true},
{
position: 'top',
offset: true,
labels: [["unstable,","dispersed"],"depressed","nervous","uncertainty","inactiv","inhibited","irresponsible","critical",["lack","of","accord"],"withdrawn"]
}]
}
}
}
var 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/2.8.0/Chart.js"></script>
</body>

Chartjs average line over bars

I use https://www.chartjs.org/. In the example below I list values for every day for two weeks. For that I want a line of the average values for this period.
Is it possible with chartjs and if so how?
I've started but it follows the bar locations and it should create a new path with fewer points.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="canvas"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.js"></script>
<script>
var ctx = document.getElementById('canvas').getContext('2d');
var mixedChart = new Chart(ctx, {
type: 'bar',
data: {
datasets: [{
label: 'Bar Dataset',
data: [1, 2, 3, 1, 3, 4, 7, 2, 4, 3, 1, 6, 5, 2],
backgroundColor: "#FF9881",
order: 2
}, {
label: 'Line Dataset',
data: [1, 2],
type: 'line',
borderColor: "#FF312D",
fill: false,
borderWidth: 1,
order: 1
}],
labels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
},
options: {
"scales": {
"yAxes": [{
"ticks": {
"beginAtZero": true
}
}]
}
}
});
</script>
</body>
</html>
I would calculate the average and spread it over the whole graph like this:
const getLineData = (initialData, lengthOfDataChunks) => {
const numOfChunks = Math.ceil(initialData.length / lengthOfDataChunks);
const dataChunks = [];
for (var i = 0; i < numOfChunks; i++) dataChunks[i] = [];
initialData.forEach((entry, index) => {
const chunkNumber = Math.floor(index / lengthOfDataChunks);
dataChunks[chunkNumber]
dataChunks[chunkNumber].push(entry);
});
const averagedChunks = dataChunks.map(chunkEntry => {
const chunkAverage = chunkEntry.reduce(sumArray) / lengthOfDataChunks;
return chunkEntry.map(chunkEntryValue => chunkAverage);
});
return averagedChunks.flat();
}
const ctx = document.getElementById('canvas').getContext('2d');
const barData = [1, 2, 3, 1, 3, 4, 7, 2, 4, 3, 1, 6, 5, 2];
const sumArray = (accumulator, currentValue) => accumulator + currentValue;
const averageBarValue = barData.reduce(sumArray) / barData.length;
const lineData = getLineData(barData, 7);
var mixedChart = new Chart(ctx, {
type: 'bar',
data: {
datasets: [{
label: 'Bar Dataset',
data: barData,
backgroundColor: "#FF9881",
order: 2
}, {
label: 'Line Dataset',
data: lineData,
type: 'line',
borderColor: "#FF312D",
fill: false,
borderWidth: 1,
order: 1
}],
labels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
},
options: {
"scales": {
"yAxes": [{
"ticks": {
"beginAtZero": true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.js"></script>
<canvas id="canvas"></canvas>
I hope I got your question right. If not, please let me know!
If your requirements are to draw just a flat, average line, I would go for
their official annotation plugin [chartjs-plugin-annotation].
I will insert a really basic, self-consistent example here, adapted from their documentation.
index.html:
<html>
<head>
<script src="index.js"></script>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
anyname.js [which you then need to browserify into the index.js source file]:
/* the following is just a shortcut to register all the needed elements, for any chart.
more info here:
https://www.chartjs.org/docs/3.3.0/getting-started/integration.html#bundlers-webpack-rollup-etc */
const Chart = require("chart.js/auto");
const annotationPlugin = require("chartjs-plugin-annotation");
function average(ctx) {
const values = ctx.chart.data.datasets[0].data;
return values.reduce((a, b) => a + b, 0) / values.length;
}
const data = {
labels: ["1", "2", "3", "4", "5", "6", "7"],
datasets: [
{
label: "Sample Series",
data: [40, 100, 54, 34, 13, 78, 41]
}
]
};
const annotation = {
type: 'line',
borderColor: 'black',
borderDash: [6, 6],
borderDashOffset: 0,
borderWidth: 3,
label: {
enabled: true,
content: (ctx) => "Average: " + average(ctx).toFixed(2),
position: 'end'
},
scaleID: 'y',
value: (ctx) => average(ctx)
};
const config = {
type: 'bar',
data,
options: {
plugins: {
title: {
display: true,
text: "Sample Chart",
font: {
size: 14
}
},
annotation: {
annotations: {
annotation
}
}
}
}
};
// the annotation plugin needs to be registered, too
Chart.register(annotationPlugin);
document.addEventListener('DOMContentLoaded', () => {
const myChart = new Chart(document.getElementById('canvas'), config);
}, false);
Node required libraries [which you need to install for browserify to work]:
chart.js -- v. 3.7.1
chartjs-plugin-annotation -- v. 1.3.1
References:
https://www.chartjs.org/chartjs-plugin-annotation/1.2.0/samples/line/average.html

Grouped bar chart with label in Chart.js

I need to recreate a chart very similar to this one:
While researching I found this example:
https://codepen.io/bencarmichael/pen/XeYJXJ
datasets: [
{
label: "American Express",
backgroundColor: "pink",
borderColor: "red",
borderWidth: 1,
data: [3, 5, 6, 7,3, 5, 6, 7] // I need labels on this values
}
]
It shows grouped bar charts. But it's lacking a label per bar. If it's not possible on Chart.js, it can be any other library.
use this code
View result in full screen mode
this is copied from the example you provided in you Question
var barChartData = {
labels: [
"Absence of OB",
"Closeness",
"Credibility",
"Heritage",
"M Disclosure",
"Provenance",
"Reliability",
"Transparency"
],
datasets: [
{
label: "American Express",
backgroundColor: "pink",
borderColor: "red",
borderWidth: 1,
data: [3, 5, 6, 7,3, 5, 6, 7],
},
{
label: "Mastercard",
backgroundColor: "lightblue",
borderColor: "blue",
borderWidth: 1,
data: [4, 7, 3, 6, 10,7,4,6]
},
{
label: "Paypal",
backgroundColor: "lightgreen",
borderColor: "green",
borderWidth: 1,
data: [10,7,4,6,9,7,3,10]
},
{
label: "Visa",
backgroundColor: "yellow",
borderColor: "orange",
borderWidth: 1,
data: [6,9,7,3,10,7,4,6]
}
]
};
var chartOptions = {
responsive: true,
legend: {
position: "top"
},
"hover": {
"animationDuration": 0
},
legend: {
"display": false
},
tooltips: {
"enabled": true
},
"animation": {
"duration": 1,
"onComplete": function () {
var chartInstance = this.chart,
ctx = chartInstance.ctx;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
this.data.datasets.forEach(function (dataset, i) {
debugger
var meta = chartInstance.controller.getDatasetMeta(i);
meta.data.forEach(function (bar, index) {
var data = dataset.data[index];
ctx.font = '10pt Verdana';
ctx.save();
ctx.translate(0,500);
ctx.rotate(-0.5*Math.PI);
var rText = 'My test value ='+data ;
ctx.fillText(rText , 90, bar._model.x+5);
ctx.restore();
});
});
}
},
title: {
display: true,
text: "Chart.js Bar Chart"
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
window.onload = function() {
var ctx = document.getElementById("canvas").getContext("2d");
window.myBar = new Chart(ctx, {
type: "bar",
data: barChartData,
options: chartOptions
});
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.0/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div id="container" style="width: 75%;">
<canvas id="canvas"></canvas>
</div>

Categories

Resources