Reputation: 519
I am creating a chart in Chart.JS and want viewers to be able to hover over a specific part of a donut chart and get both the data and a customized description of the data. For the example below, we looked for relevant research projects via the web and through a series of interviews. Right now, it shows the name of the field and the corresponding data. In addition to that, I want to define the field for a user. For example, when someone hovers over Web-Based Search I want them to see:
Web-based Search: 75
We extracted a scan of relevant research projects through web-scraping.
Similarly, I want to add a description defining the interviews field. I've added tooltips before, however it's always been something like [static string] + [data]. I haven't had to create custom definitions for each data point before. Any help is appreciated. See my CodePen also: https://codepen.io/tenebris_silentio/pen/abdgXqg
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Project Overview</title>
<script src="https://code.jquery.com/jquery-3.4.1.slim.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.css" rel="stylesheet"/>
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.js"></script>
</head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.js"></script>
<!-- Load plotly.js into the DOM -->
<script src='https://cdn.plot.ly/plotly-latest.min.js'></script>
</head>
<div class="container">
<div class="row my-3">
<div class="col">
<p class="sansserif">
<h3>Project Overview</h3></p>
</div>
</div>
<div class="row py-2">
<div class="col-md-4 py-1">
<div class="card" style="width: 33rem;">
<div class="card-body">
<canvas id="chDonut1"></canvas>
</div>
</div>
</div>
<script>
/* chart.js chart examples */
Chart.pluginService.register({
beforeDraw: function(chart) {
var width = chart.chart.width,
height = chart.chart.height,
ctx = chart.chart.ctx;
ctx.restore();
var fontSize = (height / 124).toFixed(2);
ctx.font = fontSize + "em sans-serif";
ctx.textBaseline = "middle";
var text = "";
switch(chart.chart.canvas.id){
case "chDonut1":
text = "Method";
break;
}
var textX = Math.round((width - ctx.measureText(text).width) / 2),
textY = height / 2;
ctx.fillText(text, textX, textY);
ctx.save();
}
});
// chart colors
var colors = ['#007bff','#28a745','#333333','#c3e6cb','#dc3545','#6c757d'];
var donutOptions = {
cutoutPercentage: 85,
legend: {position:'bottom', padding:5, labels: {pointStyle:'circle', usePointStyle:true}}
};
// donut 1
var chDonutData1 = {
labels: ['Web-based search', 'Interviews'],
datasets: [
{
backgroundColor: colors.slice(0,2),
borderWidth: 0,
data: [75, 25]
}
]
};
var chDonut1 = document.getElementById("chDonut1");
if (chDonut1) {
new Chart(chDonut1, {
type: 'pie',
data: chDonutData1,
options: donutOptions
});
}
</script>
Upvotes: 0
Views: 1159
Reputation: 26150
You can define a set of tooltip callback functions to obtain the desired result. This could look as follows:
tooltips: {
callbacks: {
title: (tooltipItems, data) => data.labels[tooltipItems[0].index],
label: (tooltipItems, data) => 'Count: ' + data.datasets[0].data[tooltipItems.index],
footer: (tooltipItems, data) => ['', 'Infos:'].concat(data.datasets[0].info[tooltipItems[0].index])
}
}
Note that in the
footer
callback, I return text that I defined in an array namedinfo
defined inside thedata
object.
datasets: [{
...
info: [
['This is the description', 'for Web-based search ...'],
['This is the description', 'for Interviews ...']
]
}]
Please have a look at your amended code below:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Project Overview</title>
<script src="https://code.jquery.com/jquery-3.4.1.slim.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.css" rel="stylesheet" />
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.js"></script>
<!-- Load plotly.js into the DOM -->
<script src='https://cdn.plot.ly/plotly-latest.min.js'></script>
</head>
<div class="container">
<div class="row my-3">
<div class="col">
<p class="sansserif">
<h3>Project Overview</h3>
</p>
</div>
</div>
<div class="row py-2">
<div class="col-md-4 py-1">
<div class="card" style="width: 33rem;">
<div class="card-body">
<canvas id="chDonut1"></canvas>
</div>
</div>
</div>
<script>
/* chart.js chart examples */
Chart.pluginService.register({
beforeDraw: function(chart) {
var width = chart.chart.width,
height = chart.chart.height,
ctx = chart.chart.ctx;
ctx.restore();
var fontSize = (height / 124).toFixed(2);
ctx.font = fontSize + "em sans-serif";
ctx.textBaseline = "middle";
var text = "";
switch (chart.chart.canvas.id) {
case "chDonut1":
text = "Method";
break;
}
var textX = Math.round((width - ctx.measureText(text).width) / 2),
textY = height / 2;
ctx.fillText(text, textX, textY);
ctx.save();
}
});
// chart colors
var colors = ['#007bff', '#28a745', '#333333', '#c3e6cb', '#dc3545', '#6c757d'];
var donutOptions = {
cutoutPercentage: 85,
legend: {
position: 'bottom',
padding: 5,
labels: {
pointStyle: 'circle',
usePointStyle: true
}
},
tooltips: {
callbacks: {
title: (tooltipItems, data) => data.labels[tooltipItems[0].index],
label: (tooltipItems, data) => 'Count: ' + data.datasets[0].data[tooltipItems.index],
footer: (tooltipItems, data) => ['', 'Infos:'].concat(data.datasets[0].info[tooltipItems[0].index])
}
}
};
// donut 1
var chDonutData1 = {
labels: ['Web-based search', 'Interviews'],
datasets: [{
backgroundColor: colors.slice(0, 2),
borderWidth: 0,
data: [75, 25],
info: [
['This is the description', 'for Web-based search ...'],
['This is the description', 'for Interviews ...']
]
}]
};
var chDonut1 = document.getElementById("chDonut1");
if (chDonut1) {
new Chart(chDonut1, {
type: 'pie',
data: chDonutData1,
options: donutOptions
});
}
</script>
</html>
Upvotes: 1