I am currently fiddling around with some charts, and I would like for there to be a string of text to come up as you hover over certain data points.
So for example, currently my dataset looks like this:
var data = {
labels: ["January", "February:", "March", "April", "May", "June", "July"],
datasets: [{
label: "My first dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 81, 56, 55, 40]
}]
};
I would like for example, to hover over the February : 59 point and have it display "February : 59 - Some unique text"
Thank you
first add this in html
<canvas id="myChart" width="400" height="200"></canvas>
<div id="chartjs-tooltip"></div>
:js
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 81, 56, 55, 40]
}]
};
var myLineChart = new Chart(ctx).Line(data, {
customTooltips: function (tooltip) {
var tooltipEl = $('#chartjs-tooltip');
if (!tooltip) {
tooltipEl.css({
opacity: 0
});
return;
}
tooltipEl.removeClass('above below');
tooltipEl.addClass(tooltip.yAlign);
// split out the label and value and make your own tooltip here
var parts = tooltip.text.split(":");
var innerHtml = '<span>' + parts[0].trim() + '</span> : <span><b>' + parts[1].trim() + '</b></span>';
tooltipEl.html(innerHtml);
tooltipEl.css({
opacity: 1,
left: tooltip.chart.canvas.offsetLeft + tooltip.x + 'px',
top: tooltip.chart.canvas.offsetTop + tooltip.y + 'px',
fontFamily: tooltip.fontFamily,
fontSize: tooltip.fontSize,
fontStyle: tooltip.fontStyle,
});
}
});
and some styling stuff
:css
#chartjs-tooltip {
opacity: 0;
position: absolute;
background: rgba(0, 0, 0, .7);
color: white;
padding: 3px;
border-radius: 3px;
-webkit-transition: all .1s ease;
transition: all .1s ease;
pointer-events: none;
-webkit-transform: translate(-50%, 0);
transform: translate(-50%, 0);
}
(Note that Chart.js already adds tooltip text automatically; the question above is a bit unclear. What the question is about is how to add custom text to the tooltip, rather than just the defaults that it picks - the x and y values of the given point.)
Use the callbacks field in options.tooltips. Note that the body of the tooltip is referred to as the "label".
tooltips: {
intersect: false, // makes it easier to select tooltips on mobile
callbacks: {
title: (toolTipItem, data) => {
let title = toolTipItem[0].x; // uses the x value of this point as the title
return title;
},
label: (toolTipItem, data) => {
let labels = data[toolTipItem.index!].labelText; // assumes your data has a `labelText` field.
return labels;
},
},
},
Note that some fields, like title, are passed an array of toolTipItem objects in their callback; others, like label, are passed a single object. Hence, properties of the toolTipItem object must be accessed differently for each.
Callback documentation: http://www.chartjs.org/docs/latest/configuration/tooltip.html#tooltip-callbacks
Properties you can access on the toolTipItem object - https://www.chartjs.org/docs/latest/configuration/tooltip.html#tooltip-item-interface
Some official examples: https://www.chartjs.org/docs/latest/configuration/tooltip.html#label-callback
Unofficial: How to customize the tooltip of a Chart.js 2.0 Doughnut Chart?
How to wrap long label lines?
One way or the other, split up your labels into an array, and return that; each line in the array will be on a separate line. If the lines are still too long, you'll need to use a function to detect long lines and split them into additional array items.
Related
I create charts for weather. I want to show automatically the tooltip on the last datapoint, when the chart is created. When the mouse is moved to another datapoint, the tootip should move to the new datapoint of the mouse or vanish if the mouse is outside.
https://www.chartjs.org/docs/3.8.0/samples/advanced/programmatic-events.html ist very close. Thanks!
function triggerTooltip(chart) {
const tooltip = chart.tooltip;
if (tooltip.getActiveElements().length > 0)
{ tooltip.setActiveElements([], {x: 0, y: 0}); }
else {
const chartArea = chart.chartArea;
tooltip.setActiveElements([
{
datasetIndex: 0,
index: 0,
}, {
datasetIndex: 1,
index: 0,
}],
{ x: (chartArea.left + chartArea.right) / 2,
y: (chartArea.top + chartArea.bottom) / 2, });
}
chart.update(); }
I did expect that the index controlls the bar, for the tooltip. But it makes no difference, whatever Index is set.
Also when I change x,y it is still on the same place (close to 3rd bar).
enter image description here
This can be done with the Plugin Core API in the afterDatasetUpdate hook as follows:
afterDatasetUpdate: chart => {
if (!chart.tooltip.getActiveElements().length) {
chart.tooltip.setActiveElements([{
datasetIndex: 0,
index: chart.data.datasets[0].data.length - 1
}]);
chart.update();
}
}
Please take a look at the runnable code snippet below and see how it works.
new Chart('myChart', {
type: 'line',
plugins: [{
afterDatasetUpdate: chart => {
if (!chart.tooltip.getActiveElements().length) {
chart.tooltip.setActiveElements([{
datasetIndex: 0,
index: chart.data.datasets[0].data.length - 1
}]);
chart.update();
}
}
}],
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: '# of Events',
data: [65, 59, 80, 81, 56, 55, 68],
borderColor: '#a00'
}]
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js"></script>
<canvas id="myChart" width="400" height="95"></canvas>
thanks - it is exactly, what I am looking for!
The snippet in your answer works with visible tooltip on the last data point.
When I try it in test.html in my browser (I tested firefox, edge,chrome) the tooltip is not visible.
Where is the mistake in my test.html?
<!DOCTYPE html>
<html>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js"></script>
<canvas id="myChart" width="400" height="95"></canvas>
<script type="text/javascript">
new Chart('myChart', {
type: 'line',
plugins: [{
afterDatasetUpdate: chart => {
if (!chart.tooltip.getActiveElements().length) {
chart.tooltip.setActiveElements([{
datasetIndex: 0,
index: chart.data.datasets[0].data.length - 1
}]);
chart.update();
}
}
}],
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: '# of Events',
data: [65, 59, 80, 20, 81, 56, 55, 68],
borderColor: '#a00'
}]
}
});
</script>
</body>
</html>
that is my test:
https://www.zebrafell.de/test.html
Good evening,
There's any way to alternate the chart's backgroud color for each dataSet of a result?
That's how I wish it.
enter image description here
Alternate background may be created with the use of chartjs-plugin-annotation.
Please have a look at the code snippet below that has been derived from the example code provided by the contributors of chartjs-plugin-annotation.
This code works with Chart.js 2.6.0 and it still produces a script error that may be ignored. Unfortunately I couldn't make it work with the newest version of Chart.js (currently 2.9.3) yet and I don't have time now to further investigate.
const labels = ["January", "February", "March", "April", "May", "June", "July"];
const annotations = [];
for (let i = 0; i < labels.length; i++) {
if (i % 2 == 0) {
annotations.push({
drawTime: "beforeDatasetsDraw",
type: "box",
xScaleID: "x-axis-0",
yScaleID: "y-axis-0",
xMin: labels[i],
xMax: labels[i + 1],
backgroundColor: "rgba(128, 128, 128, 0.5)",
borderColor: "rgb(128, 128, 128)",
borderWidth: 1
});
}
};
new Chart('chart', {
type: "bar",
data: {
labels: labels,
datasets: [{
label: "Dataset 1",
backgroundColor: 'red',
data: [95, 70, 55, -88, -64, 34, -55],
categoryPercentage: 1,
barPercentage: 0.8
},
{
label: "Dataset 2",
backgroundColor: 'green',
data: [81, 58, 30, -91, -74, 20, -40],
categoryPercentage: 1,
barPercentage: 0.9
}
]
},
options: {
responsive: true,
tooltips: {
mode: "index",
intersect: true
},
annotation: {
annotations: annotations
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/0.5.7/chartjs-plugin-annotation.js"></script>
<canvas id="chart" height="90"></canvas>
we can use annotation plugin to do this
import annotationPlugin from "chartjs-plugin-annotation";
import {Chart} from 'chart.js';
Chart.register(annotationPlugin);
this code will add a box to our chart
{
type: 'box', #type of draw
drawTime: 'beforeDraw', #this will decide background or foreground
yMin: 5, #value min on y axis
yMax: 10, #value max on y axis
borderColor: 'rgb(242, 244, 248, 0.9)', #border color of the box
borderWidth: 1, #boarder width for box
backgroundColor: '#F2F4F8', #colour of the box
}
Out of this code
refer to this post here on how to do this: https://medium.com/#omi10859/alternative-background-lines-in-chartjs-a626ce4d3bcb
I have searched through for the solution but I have found solution to pie charts only. For example this one : Chart.js v2: How to make tooltips always appear on pie chart?
I just want make the tooltip visible without hovering. I have tried registering new pluginService but its not working and its producing this error
Uncaught TypeError: Cannot read property 'call' of undefined
this is what I have so far
Chart.pluginService.register({
beforeRender: function (chart) {
if (chart.config.options.showAllTooltips) {
// create an array of tooltips
// we can't use the chart tooltip because there is only one tooltip per chart
chart.pluginTooltips = [];
chart.config.data.datasets.forEach(function (dataset, i) {
chart.getDatasetMeta(i).data.forEach(function (sector, j) {
chart.pluginTooltips.push(new Chart.Tooltip({
_chart: chart.chart,
_chartInstance: chart,
_data: chart.data,
_options: chart.options,
_active: [sector]
}, chart));
});
});
// turn off normal tooltips
chart.options.tooltips.enabled = false;
}
},
afterDraw: function (chart, easing) {
if (chart.config.options.showAllTooltips) {
// we don't want the permanent tooltips to animate, so don't do anything till the animation runs atleast once
if (!chart.allTooltipsOnce) {
if (easing !== 1)
return;
chart.allTooltipsOnce = true;
}
// turn on tooltips
chart.options.tooltips.enabled = true;
Chart.helpers.each(chart.pluginTooltips, function (tooltip) {
tooltip.initialize();
tooltip.update();
// we don't actually need this since we are not animating tooltips
tooltip.pivot();
tooltip.transition(easing).draw();
});
chart.options.tooltips.enabled = false;
}
}
})
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 81, 56, 55, 40]
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
},
showAllTooltips: true
}
});
appreciate any helps tq
When using the latest stable version of Chart.js (2.9.3), it works with the following changes.
Instead of Chart.pluginService.register, use Chart.plugin.register
Instead of change _options : chart.options write _options : chart.options.tooltips
Please have a look at your amended code below.
Chart.plugins.register({
beforeRender: function(chart) {
if (chart.config.options.showAllTooltips) {
// create an array of tooltips,
// we can't use the chart tooltip because there is only one tooltip per chart
chart.pluginTooltips = [];
chart.config.data.datasets.forEach(function(dataset, i) {
chart.getDatasetMeta(i).data.forEach(function(sector, j) {
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; // turn off normal tooltips
}
},
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;
}
}
});
new Chart("chart", {
type: 'line',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 81, 56, 55, 40]
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
},
showAllTooltips: true
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="chart" height="100"></canvas>
I would like to change font size and border colors for this chart. Hence I don't know how to do it, I tried to put these options at different places but nothing seems to work. I can't get the logic of the binding between angular-chart options and Chart.js options, is there a common way to manipulate them?
Here's the directive:
<canvas class="chart chart-line" chart-y-axes="axes" chart-data="data" chart-labels="labels"
chart-series="series" chart-options="options" chart-legend="true" chart-colours="colours"></canvas>
Here are the scope definitions:
$scope.labels = ["January", "February", "March", "April", "May", "June", "July"];
$scope.series = ['Series A', 'Series B'];
$scope.axes = ["y-axis-1", "y-axis-2"];
$scope.data = [
[65, 59, 80, 81, 56, 55, 40],
[28, 48, 40, 19, 86, 27, 90]
];
$scope.colours = [{
fillColor: 'rgba(151,187,205,0.2)',
strokeColor: 'rgba(151,187,205,1)',
pointColor: 'rgba(151,187,205,1)',
pointStrokeColor: '#fff',
pointHighlightFill: '#fff',
pointHighlightStroke: 'rgba(151,187,205,0.8)'
}]
$scope.options = {
datasetFill: false,
showLines: true,
elements:
{
line:
{
fill: false,
tension: 0.0001
},
point:
{
radius: 0
}
},
scales:
{
yAxes: [
{
type:"linear",
id:$scope.axes[0],
gridLines:
{
display: false
}
},
{
type:"linear",
id:$scope.axes[1],
position: "right",
gridLines:
{
display: false
},
scaleLabel:
{
display: true
}
}]
},
};
Changing the colors through chart-colors just doesn't work.
Since you have 2 series, make sure you have 2 entries in $scope.colours i.e.
...
$scope.colours = [{
fillColor: 'rgba(151,187,205,0.2)',
strokeColor: 'red',
pointColor: 'rgba(151,187,205,1)',
pointStrokeColor: '#fff',
pointHighlightFill: '#fff',
pointHighlightStroke: 'rgba(151,187,205,0.8)'
}, {
fillColor: 'rgba(151,187,205,0.2)',
strokeColor: 'blue',
pointColor: 'rgba(151,187,205,1)',
pointStrokeColor: '#fff',
pointHighlightFill: '#fff',
pointHighlightStroke: 'rgba(151,187,205,0.8)'
}]
...
Fiddle - http://jsfiddle.net/cpdh1g19/ (the color for the first line will change after 2 seconds)
By the look of the options, you're using chart.js 2.0, you need to use the latest angular-chart.js.
Note the attribute is now chart-colors and the color properties have changed in chart.js 2.0.
I am using chart.js .Bar() charts.
However, on some conditions there may be no data in the system. Short of creating empty (dummy) datasets, can I somehow make chartjs draw an empty plot?
Edit: I edited the post to show horizontal lines of an empty graph as #zazu asked for it
In this sample, I set up a Chart.js line graph, providing a first dataset with data (in order to scale the grid vertical axis and make the horizontal lines visible), and a second one with empty data. This results in an empty graph, but with the full grid visible:
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
// invisible dataset
{
label: "",
fillColor: "rgba(220,220,220,0.0)",
strokeColor: "rgba(220,220,220,0)",
pointColor: "rgba(220,220,220,0)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
// change this data values according to the vertical scale
// you are looking for
data: [65, 59, 80, 81, 56, 55, 40]
},
// your real chart here
{
label: "My dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: []
}
]
};
var options = {
animation: false,
///Boolean - Whether grid lines are shown across the chart
scaleShowGridLines : true,
//Boolean - Whether to show vertical lines (except Y axis)
scaleShowVerticalLines: true,
showTooltips: false
};
var ctx = document.getElementById("myChart").getContext("2d");
var myLineChart = new Chart(ctx).Line(data, options);
<script src="http://www.chartjs.org/assets/Chart.js"></script>
<canvas id="myChart" width="400" height="400"></canvas>
JSFiddle here.