Reputation: 375
I'm a little stuck on how I would achieve this since it's a little unorthodox in relation to what the plugin does.
I'm attempting for each dataset to keep the last tooltip open at all times and leave the rest to be displayed on hover.
Currently, I'm using this to keep them all displayed:
Chart.plugins.register({
beforeRender: function (chart) {
if (chart.config.options.showAllTooltips) {
chart.pluginTooltips = [];
chart.config.data.datasets.forEach(function (dataset, i) {
console.log(chart);
chart.getDatasetMeta(i).data.forEach(function (sector, j) {
console.log(sector);
chart.pluginTooltips.push(new Chart.Tooltip({
_chart: chart.chart,
_chartInstance: chart,
_data: chart.data,
_options: chart.options.tooltips,
_active: [sector]
}, chart));
});
});
chart.options.tooltips.enabled = false;
}
},
afterDraw: function (chart, easing) {
if (chart.config.options.showAllTooltips) {
if (!chart.allTooltipsOnce) {
if (easing !== 1) {
return;
}
chart.allTooltipsOnce = true;
}
chart.options.tooltips.enabled = true;
Chart.helpers.each(chart.pluginTooltips, function (tooltip) {
tooltip.initialize();
tooltip.update();
tooltip.pivot();
tooltip.transition(easing).draw();
});
chart.options.tooltips.enabled = false;
}
}
});
Is there a way to only do this for the last tooltip in each dataset?
I've come across a way to hide tooltips:
filter: function (tooltipItem, data) {
var label = data.labels[tooltipItem.index];
if (label === labels[labels.length - 1]) {
console.log(tooltipItem);
} else {
return true;
}
}
But this just doesn't display them whatsoever since it's returning false
.
Ultimately it will look like this, with the other tooltips displaying on hover of the corresponding node:
Any help greatly appreciated.
Upvotes: 1
Views: 1100
Reputation: 1129
So this is the entire hmtl file with all relevant code. As I said, I am no programmer. This effort is from loads of trial and error, including several bits of code from stackoverflow questions.
<script>
$(document).ready(function () {
showtempGraph();
});
function showtempGraph()
{
{
$.post("temperaturedata.php",
function (data)
{
console.log(data);
var temptime = [];
var temp = [];
for (var i in data) {
temptime.push(data[i].timestamp);
temp.push(data[i].temperature);
}
var tempmin = Math.min(...temp);
var tempmax = Math.max(...temp);
var charttempdata = {
labels: temptime,
datasets: [
{
label: 'Temperatur',
pointRadius: 3,
backgroundColor: 'rgba(26, 137, 245, 0.2)',
borderColor: 'rgba(26, 137, 245, 1)',
hoverBackgroundColor: 'rgba(255, 255, 255, 1)',
hoverBorderColor: 'rgba(255, 255, 255, 1)',
pointBackgroundColor: 'rgba(12, 68, 122, 1)',
pointHoverBorderColor: "rgba(255, 255, 255, 0.8)",
data: temp
}
]
};
var graphtempTarget = $("#tempgraphCanvas");
var linetempGraph = new Chart(graphtempTarget, {
type: 'line',
data: charttempdata,
options: {
maintainAspectRatio: false,
tooltips: {
enabled: true,
custom: function(tooltip) {
if (!tooltip) return;
tooltip.displayColors = false;
},
callbacks: {
title: function(tooltipItems, tempdata) {
return 'Klokken: ' + tooltipItems[0].xLabel;
},
label: function(tooltipItem, tempdata) {
return 'Temperatur: ' + Number(tooltipItem.yLabel).toFixed(2) + '°C';
}
}
},
legend: {
display: false,
},
responsive: true,
scales: {
xAxes: [{
type: 'time',
time: {
displayFormats: {
hour: 'HH:mm'
},
tooltipFormat: 'HH:mm',
},
unit : 'day',
gridLines: {
color: '#999999',
lineWidth: 1
},
ticks: {
fontColor: "#fff",
}
}],
yAxes: [
{
type: 'linear',
position: 'left',
gridLines: {
color: '#999999',
lineWidth: 1
},
ticks: {
fontColor: "#fff",
}
}, {
type: 'linear',
position: "right",
afterUpdate: function(scaleInstance) {
console.dir(scaleInstance);
},
gridLines: {
color: '#999999)',
lineWidth: 0.5
},
ticks: {
stepSize: tempmax - tempmin,
min: tempmin,
max: tempmax,
mirror: true,
padding: -10,
fontColor: "#fff",
fontSize: 18,
callback: function(value) {
return value + '°C';
}
},
scaleLabel: {
display: true,
labelString: '°C',
fontColor: "#fff",
fontSize: 14
}
}]
},
}
});
});
}
}
</script>
Upvotes: -1
Reputation: 17337
I would try to use chartjs-plugin-datalabels
for such task.
You can try it out directly on their pages - scriptable interactions
Setting some random data:
var DATA_COUNT = 8;
var labels = [];
Utils.srand(100);
for (var i = 0; i < DATA_COUNT; ++i) {
labels.push('' + i);
}
var DATA_COUNT = 8;
var labels = [];
Utils.srand(100);
for (var i = 0; i < DATA_COUNT; ++i) {
labels.push('' + i);
}
Here I did some changes
{
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'France',
backgroundColor: Utils.color(0),
borderColor: Utils.color(0),
data: Utils.numbers({
count: DATA_COUNT,
min: 10,
max: 100
}),
datalabels: {
align: function(context) {
return context.active ? 'start' : 'center';
}
}
}, {
label: 'Canada',
backgroundColor: Utils.color(1),
borderColor: Utils.color(1),
data: Utils.numbers({
count: DATA_COUNT,
min: 0,
max: 100
})
}, {
label: 'USA',
backgroundColor: Utils.color(2),
borderColor: Utils.color(2),
data: Utils.numbers({
count: DATA_COUNT,
min: 0,
max: 100
}),
datalabels: {
align: function(context) {
return context.active ? 'end' : 'center';
}
}
}]
},
options: {
plugins: {
datalabels: {
backgroundColor: function(context) {
return context.active ? context.dataset.backgroundColor : 'white';
},
borderColor: function(context) {
return context.dataset.backgroundColor;
},
borderRadius: function(context) {
return context.active ? 0 : 1;
},
borderWidth: 1,
color: function(context) {
return context.active ? 'white' : context.dataset.backgroundColor;
},
font: {
weight: 'bold'
},
formatter: function(value, context) {
value = Math.round(value * 100) / 100;
if (context.dataIndex === context.dataset.data.length - 1) {
return context.dataset.label + '\n' + value + '%';
} else {
return context.active
? context.dataset.label + '\n' + value + '%'
: ''
}
},
offset: 8,
padding: 0,
textAlign: 'center'
}
},
// Core options
aspectRatio: 5 / 3,
layout: {
padding: {
bottom: 16,
right: 40,
left: 8,
top: 40
}
},
hover: {
mode: 'index',
intersect: false
},
elements: {
line: {
fill: false
}
},
scales: {
yAxes: [{
stacked: true
}]
}
}
}
The main part here is:
formatter: function(value, context) {
value = Math.round(value * 100) / 100;
if (context.dataIndex === context.dataset.data.length - 1) {
return context.dataset.label + '\n' + value + '%';
} else {
return context.active
? context.dataset.label + '\n' + value + '%'
: ''
}
},
The formatter:
where I show the label permanently only for context.dataIndex === context.dataset.data.length - 1
.
In other cases if it is inactive I show only empty box in other case (hover) I show the information.
Upvotes: 3