Unique identifier in Chartjs Bar segments? - chart.js

I want to make my bar-chart interactive by allowing the user to click on a slice to drill down. I believe that the way to do this is to create an onclick handler on the canvas, and use getSegmentsAtEvent() to determine which slice was clicked. I see one example in Pie chart works but in bar type it doesn't. Any ideas?
This works in Pie type, but not with Bar type,
Chart.types.Pie.extend({
name: "PieUnique",
addData: function(segment, atIndex, silent) {
var index = atIndex || this.segments.length;
this.segments.splice(index, 0, new this.SegmentArc({
value: segment.value,
outerRadius: (this.options.animateScale) ? 0 : this.outerRadius,
innerRadius: (this.options.animateScale) ? 0 : (this.outerRadius / 100) * this.options.percentageInnerCutout,
fillColor: segment.color,
highlightColor: segment.highlight || segment.color,
showStroke: this.options.segmentShowStroke,
strokeWidth: this.options.segmentStrokeWidth,
strokeColor: this.options.segmentStrokeColor,
startAngle: Math.PI * this.options.startAngle,
circumference: (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),
label: segment.label,
//add option passed
id: segment.id
}));
if (!silent) {
this.reflow();
this.update();
}
},
});
var pieData = [{
value: 300,
color: "#F7464A",
highlight: "#FF5A5E",
label: "Red",
id: "1-upi"
}, {
value: 50,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Green",
id: "2-upi"
}, {
value: 100,
color: "#FDB45C",
highlight: "#FFC870",
label: "Yellow",
id: "3-upi"
}, {
value: 40,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey",
id: "4-upi"
}, {
value: 120,
color: "#4D5360",
highlight: "#616774",
label: "Dark Grey",
id: "5-upi"
}];
var ctx = document.getElementById("chart-area").getContext("2d");
window.myPie = new Chart(ctx).PieUnique(pieData);
document.getElementById("chart-area").onclick = function(evt) {
var activePoints = window.myPie.getSegmentsAtEvent(evt);
if (activePoints[0]) {
var label = activePoints[0].label;
var value = activePoints[0].value;
var id = activePoints[0].id;
alert('label = ' + label + ' | value = ' + value + ' | id = ' + id);
}
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.1.1/Chart.min.js"></script>
<canvas id="chart-area"></canvas>
I expect to create the same functionality but in Bar type.

First it worth to mention the version that you are using is the old 1.1.
You have a couple of problems here, to change the chart type you will first need to change how you set the pieData variable, after that the getSegmentsAtEvent event only works with the pie type, the proper event is getBarsAtEvent.
Here is an working example (please note that I haven't used the original chart data):
Chart.types.Bar.extend({
name: "PieUnique",
addData: function(segment, atIndex, silent) {
var index = atIndex || this.segments.length;
this.segments.splice(index, 0, new this.SegmentArc({
value: segment.value,
outerRadius: (this.options.animateScale) ? 0 : this.outerRadius,
innerRadius: (this.options.animateScale) ? 0 : (this.outerRadius / 100) * this.options.percentageInnerCutout,
fillColor: segment.color,
highlightColor: segment.highlight || segment.color,
showStroke: this.options.segmentShowStroke,
strokeWidth: this.options.segmentStrokeWidth,
strokeColor: this.options.segmentStrokeColor,
startAngle: Math.PI * this.options.startAngle,
circumference: (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),
label: segment.label,
//add option passed
id: segment.id
}));
if (!silent) {
this.reflow();
this.update();
}
},
});
var pieData = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.75)",
highlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 81, 56, 55, 40]
},
{
label: "My Second dataset",
fillColor: "rgba(151,187,205,0.5)",
strokeColor: "rgba(151,187,205,0.8)",
highlightFill: "rgba(151,187,205,0.75)",
highlightStroke: "rgba(151,187,205,1)",
data: [28, 48, 40, 19, 86, 27, 90]
}
]
};
var ctx = document.getElementById("chart-area").getContext("2d");
window.myPie = new Chart(ctx).PieUnique(pieData);
document.getElementById("chart-area").onclick = function(evt) {
var activePoints = window.myPie.getBarsAtEvent(evt);
if (activePoints[0]) {
var label = activePoints[0].label;
var value = activePoints[0].value;
var id = activePoints[0].id;
alert('label = ' + label + ' | value = ' + value + ' | id = ' + id);
}
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.1.1/Chart.min.js"></script>
<canvas id="chart-area"></canvas>

Related

Line chart out of axis boundary after extended the chart draw function

I referred to "How to change line segment color of a line graph in Chart.js" and extended the chart to redraw the line segment with a different color.
But after adding plugin "chartjs-plugin-zoom" to support zoom in/out the chart, I could see the line chart is out of axis boundary. See the following code.
https://jsfiddle.net/sd9rx84g/2/
var ctx = document.getElementById('myChart').getContext('2d');
//adding custom chart type
Chart.defaults.multicolorLine = Chart.defaults.line;
Chart.controllers.multicolorLine = Chart.controllers.line.extend({
draw: function(ease) {
var
startIndex = 0,
meta = this.getMeta(),
points = meta.data || [],
colors = this.getDataset().colors,
area = this.chart.chartArea,
originalDatasets = meta.dataset._children
.filter(function(data) {
return !isNaN(data._view.y);
});
function _setColor(newColor, meta) {
meta.dataset._view.borderColor = newColor;
}
if (!colors) {
Chart.controllers.line.prototype.draw.call(this, ease);
return;
}
for (var i = 2; i <= colors.length; i++) {
if (colors[i-1] !== colors[i]) {
_setColor(colors[i-1], meta);
meta.dataset._children = originalDatasets.slice(startIndex, i);
meta.dataset.draw();
startIndex = i - 1;
}
}
meta.dataset._children = originalDatasets.slice(startIndex);
meta.dataset.draw();
meta.dataset._children = originalDatasets;
points.forEach(function(point) {
point.draw(area);
});
}
});
var chart = new Chart(ctx, {
// The type of chart we want to create
type: 'multicolorLine',
// The data for our dataset
data: {
labels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
datasets: [{
label: "My First dataset",
borderColor: 'rgb(255, 99, 132)',
data: [35, 10, 5, 2, 20, 30, 45, 0, 10, 5, 2, 20, 30, 45],
//first color is not important
colors: ['', 'red', 'green', 'blue', 'red', 'brown', 'black']
}]
},
// Configuration options go here
options: {
plugins: {
zoom: {
pan: {
// pan options and/or events
enabled: true,
mode: 'xy'
},
zoom: {
enabled: true,
drag: false,
mode: 'x',
speed: 1
}
}
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.3"></script>
<script src="https://cdn.jsdelivr.net/npm/hammerjs#2.0.8"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom#0.7.7"></script>
<canvas id="myChart"></canvas>
line chart out of axis boundary
How can I resolve this issue?
Thanks
Forrest

ChartJS multiple tooltip callbacks not working

I'm trying to calculate the sum of the dataset values at the end of a tooltip in ChartJS.
When I execute this code in "label" callback, works correctly. However, when I execute this code in a different callback in "afterBody" or "footer" callback, it results in NaN.
new Chart(document.getElementById("line-chart"), {
type: 'line',
data: {
labels: [2018, 2019, 2020],
datasets: [{
data: [1.09, 1.48, 2.48],
label: "ABC",
borderColor: "#3e95cd",
fill: false
}, {
data: [0.63, 0.81, 0.95],
label: "DEF",
borderColor: "#8e5ea2",
fill: false
}, {
data: [0.17, 0.17, 0.18],
label: "GHI",
borderColor: "#3cba9f",
fill: false
}]
},
options: {
title: {
display: true,
text: 'Past 2FY + Current FY Estimate, US$ millions'
},
tooltips: {
mode: 'index',
callbacks: {
label: function(tooltipItem, data) {
if (tooltipItem.index > 0) {
var previousdata = tooltipItem.index - 1;
var growth = ", YoY: " + ((data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index] / data.datasets[tooltipItem.datasetIndex].data[previousdata] * 100) - 100).toFixed(1) + "%";
} else {
var growth = '';
};
return data.datasets[tooltipItem.datasetIndex].label + ': $' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index] + growth;
},
afterBody: function(tooltipItem, data){
var total = 0;
for(var i=0; i < data.datasets.length; i++)
total += data.datasets[i].data[tooltipItem.index];
return 'Sum:'+total;
}
}
}
}
});
<canvas id="line-chart"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
Any help will be great!
I expect tooltip "Sum:" returns the sum of dataset values (in this case 'ABC' + 'CDE' + 'GHI' values).
Your use case is the given example for tooltip callbacks on the Chart.js samples page with the following code:
// Use the footer callback to display the sum of the items showing in the tooltip
footer: function(tooltipItems, data) {
var sum = 0;
tooltipItems.forEach(function(tooltipItem) {
sum += data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
});
return 'Sum: ' + sum;
}
Editing your snippet as per the above example seems to yield the result you want, although you probably want it formatted to match the rest of your tooltip:
new Chart(document.getElementById("line-chart"), {
type: 'line',
data: {
labels: [2018, 2019, 2020],
datasets: [{
data: [1.09, 1.48, 2.48],
label: "ABC",
borderColor: "#3e95cd",
fill: false
}, {
data: [0.63, 0.81, 0.95],
label: "DEF",
borderColor: "#8e5ea2",
fill: false
}, {
data: [0.17, 0.17, 0.18],
label: "GHI",
borderColor: "#3cba9f",
fill: false
}]
},
options: {
title: {
display: true,
text: 'Past 2FY + Current FY Estimate, US$ millions'
},
tooltips: {
mode: 'index',
callbacks: {
label: function(tooltipItem, data) {
if (tooltipItem.index > 0) {
var previousdata = tooltipItem.index - 1;
var growth = ", YoY: " + ((data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index] / data.datasets[tooltipItem.datasetIndex].data[previousdata] * 100) - 100).toFixed(1) + "%";
} else {
var growth = '';
};
return data.datasets[tooltipItem.datasetIndex].label + ': $' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index] + growth;
},
footer: function(tooltipItems, data) {
var sum = 0;
tooltipItems.forEach(function(tooltipItem) {
sum += data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
});
return 'Sum: ' + sum;
}
}
}
}
});
<canvas id="line-chart"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>

ChartJS line-chart set background-opacity

I've tried multiple examples but i'm unable to get my line-chart to have background-transparency, as of now, it's blue, but the color i'm trying to set is orange (rgba(255, 145, 68, 0.2)).
TL;DR: How do I set the fill-opacity on my line-chart graph?
I've followed countless of tutorials, but all of them seem to set the background-color in dataset, which is not what I want, since i'm using dynamic data. The code is in a TypeScript component with tons of functionality built upon it, so it's quite hard to extract the code and make it work in a jsfiddle.
When i set fill:true under elements: { line: { the graph will get the fill as shown in the image below. But i'm unable to set the background-opacity here,
I've tried these attributes: backgroundColor, fillColor
Here's the code atleast:
import {
Component
} from '../../decorators/component.decorator';
import * as EsChart from '../../../../node_modules/chart.js/dist/Chart.bundle.js';
import * as angular from 'angular';
#Component({
templateUrl: 'app/dashboard-components/es-line-chart/es-line-chart.component.html',
bindings: {
esLineChartId: '#',
chartTitle: '#',
labels: '#',
esScaleMax: '#',
esScaleMaxSecond: '#',
esScaleStepW: '#',
esScaleStepWSecond: '#',
esScaleMin: '#',
esScaleMinSecond: '#',
lowerOkValue: '#',
targetValue: '#',
upperOkValue: '#',
chartDataValueSuffix: '#',
datasets: '#',
esXLabelSkips: '#'
}
})
export default class LineChartComponent {
$ctrl: any = this;
getChartOptions(lineChartData, secondYAxis, xLabelSkips) {
return {
type: 'line',
data: lineChartData,
options: {
responsive: true,
maintainAspectRatio: false,
title: {
display: true,
text: this.$ctrl.chartTitle
},
legend: {
display: true,
labels: {
boxWidth: 12
}
},
tooltips: {
enabled: true,
mode: 'index',
intersect: false,
filter: function(tooltipItem, data) {
return !data.datasets[tooltipItem.datasetIndex].tooltipHidden;
},
callbacks: {
label: function(tooltipItem, data) {
var currentDataset = data.datasets[tooltipItem.datasetIndex];
var label = currentDataset.label + ': ';
label += currentDataset.data[tooltipItem.index] + (currentDataset.dataSuffix ? " " + currentDataset.dataSuffix : "");
return label;
}
}
},
elements: {
line: {
tension: 0, // disables bezier curves
borderWidth: 3, // Line stroke width in pixels
fill: true,
fillColor: "rgba(255, 145, 68, 0.2)",
strokeColor: "rgba(255, 145, 68, 0.2)",
pointColor: "rgba(255, 145, 68, 1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(255, 145, 68, 1)"
},
point: { // disable the circles/points in the chart lines
radius: 0,
hitRadius: 0,
hoverRadius: 0
},
},
scales: {
xAxes: [{
display: true,
type: 'category',
ticks: {
autoSkip: xLabelSkips,
maxRotation: 45
},
afterFit: (scale) => {
scale.height = 100;
}
}],
yAxes: [{
id: 'y-axis-0',
display: true,
position: 'left',
ticks: {
stepSize: this.$ctrl.esScaleStepW ? eval(this.$ctrl.esScaleStepW) : 0.5, // grid lines on yAxis with value distance of stepSize
suggestedMin: (eval(this.$ctrl.esScaleMin)),
suggestedMax: (eval(this.$ctrl.esScaleMax))
}
},
{
id: 'y-axis-1',
display: secondYAxis,
position: 'right',
ticks: {
stepSize: this.$ctrl.esScaleStepWSecond ? eval(this.$ctrl.esScaleStepWSecond) : 0.5, // grid lines on yAxis with value distance of stepSize
suggestedMin: (eval(this.$ctrl.esScaleMinSecond)),
suggestedMax: (eval(this.$ctrl.esScaleMaxSecond))
}
}
]
}
}
};
}
getExtraDatasets(datasetType: string, dataLabel: string, fillValue: number, chartSpan: number) {
var dataFill = [];
for (var i = 0; i < chartSpan; i++) {
dataFill.push(fillValue);
}
return {
label: dataLabel,
borderColor: datasetType === "limit" ? 'rgba(205, 8, 4, 1)' : datasetType === "target" ? 'rgba(20, 180, 2, 1)' : 'rgba(0, 0, 0, 0.5)',
borderWidth: 0.5,
//tooltipHidden: true,
data: dataFill
};
}
removeEmptyDatasets() {
//var test = "[{label: 'Verklig cykeltid',borderColor: 'rgba(60, 141, 188, 0.75)',borderWidth: 4,data: },{label: 'Kalkylerad cykeltid',borderColor: 'rgba(205, 108, 104, 0.75)',borderWidth: 4,data: [59]}]";
this.$ctrl.datasets = this.$ctrl.datasets.replace(/data: *,/g, "data: [],");
this.$ctrl.datasets = this.$ctrl.datasets.replace(/data: *}/g, "data: []}");
this.$ctrl.datasets = this.$ctrl.datasets.replace(/: *,/g, ": 0,");
this.$ctrl.datasets = this.$ctrl.datasets.replace(/: *}/g, ": 0}");
var sets = this.$ctrl.datasets.match(/\{[^\{\}]*\}/g);
for (var i = 0; i < sets.length; i++) {
if (sets[i].match(/data: *\[\]/g)) {
//console.log("no data", sets[i]);
sets[i] = "";
}
}
this.$ctrl.datasets = ("[" + (sets.join()).replace(/^,|,$/g, "") + "]");
}
$onInit() {
var canvas = $("#" + this.$ctrl.esLineChartId + " .lineChart").get(0).getContext("2d");
this.removeEmptyDatasets();
//console.log(this.$ctrl.datasets);
var lineChartData = {
labels: this.$ctrl.labels ? eval(this.$ctrl.labels) : [],
datasets: this.$ctrl.datasets ? eval(this.$ctrl.datasets) : []
};
if (this.$ctrl.upperOkValue) {
lineChartData.datasets = lineChartData.datasets.concat(this.getExtraDatasets("limit", "Övre gräns", eval(this.$ctrl.upperOkValue), (lineChartData.labels).length));
}
if (this.$ctrl.targetValue) {
lineChartData.datasets = lineChartData.datasets.concat(this.getExtraDatasets("target", "Målvärde", eval(this.$ctrl.targetValue), (lineChartData.labels).length));
}
if (this.$ctrl.lowerOkValue) {
lineChartData.datasets = lineChartData.datasets.concat(this.getExtraDatasets("limit", "Undre gräns", eval(this.$ctrl.lowerOkValue), (lineChartData.labels).length));
}
var secondYAxis = false;
for (var i = 0; i < (lineChartData.datasets).length; i++) {
// set backgroundColor to be the same as borderColor so that tooltip and legend items look better
(lineChartData.datasets[i]).backgroundColor = (lineChartData.datasets[i]).borderColor;
// Activate the second y axis if a dataset uses it
if ((lineChartData.datasets[i]).yAxisID == 'y-axis-1') {
secondYAxis = true;
}
// Use standard data suffix if defined and no special data suffix is defined for the dataset
if (!((lineChartData.datasets[i]).dataSuffix) && (this.$ctrl.chartDataValueSuffix)) {
(lineChartData.datasets[i]).dataSuffix = this.$ctrl.chartDataValueSuffix;
}
}
var xLabelSkips = this.$ctrl.esXLabelSkips ? eval(this.$ctrl.esXLabelSkips) : false;
var chartOptions = this.getChartOptions(lineChartData, secondYAxis, xLabelSkips);
var lineChart = new EsChart(canvas, chartOptions);
}
}
resources i've followed:
http://tobiasahlin.com/blog/chartjs-charts-to-get-you-started/
https://www.chartjs.org/docs/latest/configuration/elements.html
https://canvasjs.com/docs/charts/chart-options/data/fill-opacity/
Image:

ChartNew.js - Remove/Hide zero label from Pie Chart

I'm trying to remove zero(0) label from pie chart in ChartNew.js.
Can't figure it out.
Below is the example:
var pieData = [
{
value: 0,
color: "sandybrown",
title: "label1",
},
{
value: 10,
color: "gold",
title: "label2",
},
{
value: 46,
color: "darkviolet",
title: "label3",
},
{
value: 0,
color: "green",
title: "label4",
},
{
value: 33,
color: "DeepSkyBlue",
title: "label5",
}
];
var myoptions = {
animateRotate : true,
animateScale : false,
animationByData : false,
animationSteps : 50,
canvasBorders : true,
canvasBordersWidth : 0,
canvasBordersColor : "black",
legend : true,
inGraphDataShow : true,
animationEasing: "linear",
annotateDisplay : true,
spaceBetweenBar : 5,
graphTitleFontSize: 18,
extrapolateMissingData : false
};
var myPie = new Chart(document.getElementById("canvas1").getContext("2d")).Pie(pieData, myoptions);
<SCRIPT src='https://rawgit.com/FVANCOP/ChartNew.js/master/ChartNew.js'></SCRIPT>
<canvas id="canvas1" height="500" width="500"></canvas>
[https://jsfiddle.net/boxxevolution/wb64oL66/2/][1]
Im trying to remove label1 and label4 from the chart.
As suggested by V-Q-A NGUYEN, add the following line in options,
inGraphDataTmpl: "<%=(v6 > 0 ? v6+' %' : ' ')%>",

ChartJS Line Graph - Multiple Lines, Show one Value on Tooltip

I'm trying to make a Graph which has to show the Account movement from each Customer.
What I'm trying to do
I've tree lines ;
First line : The minimum balance, if the customer has less than the min. balance, his balance will auto load from his bank account.
Second Line : The current balance
Third Line: The maximum balance : If the customer has more than the max. balance he will become the difference from the system on his bank account.
My Problem
Link to the picture : chartjs tooltip problem
As you see in the tooltip are the all 3 values. The values of the straight lines are irrelevant for the customer because the Limits (max and min are setted from the customer his own) .
To achieve this you can extend the line graph to add an option to show/hide tool-tips on a per dataset basses. The annoying thing is there are only a few changes but whole methods have to be overridden to get the changes in there so the below looks like a lot but its basically 3 changes to the following methods
Initialize - added option to store showTooltip option in each point
getPointsAtEvent - added check to make sure we want to disaply a tool tip when getting points
showTooltip - added check again to make sure we want to dispaly a tool tip
to then use it the chart is set up the same but instead you make it a LineTooltip (thats what i have called the extended chart) and pass anextra option in the datasets call showToolip.
datasets: [{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.75)",
highlightStroke: "rgba(220,220,220,1)",
showTooltip: false, //NEW OPTION DON"T NEED TO INCLUDE IT IF YOU WANT TO DISPLAY BUT WON"T HURT IF YOU DO
data: [15, 10, 10, 10, 10, 10, 10]
}, {
label: "My second dataset",
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.75)",
highlightStroke: "rgba(220,220,220,1)",
showTooltip: false, //NEW OPTION DON"T NEED TO INCLUDE IT IF YOU WANT TO DISPLAY BUT WON"T HURT IF YOU DO
data: [100, 100, 100, 100, 100, 100, 100]
}, {
label: "My third dataset",
fillColor: "rgba(151,187,205,0.5)",
strokeColor: "rgba(151,187,205,0.8)",
highlightFill: "rgba(151,187,205,0.75)",
highlightStroke: "rgba(151,187,205,1)",
data: [28, 48, 40, 19, 86, 27, 90]
}]
i have added bigger comment banners in the below code to try and highlight where the changes got made. I have also added this feature to my fork of chartjs as this could be useful to more people https://github.com/leighquince/Chart.js, using this you can just use a normal line chart and add the showTooltip
Below is the example of extending the Line into a custom chart to include this feature, ive called in LineTooltip as but could be called anything you like that.
Chart.types.Line.extend({
name: "LineTooltip",
/*
* we have to add one item in the init so need to rewrite it again here with the one edit
*/
initialize: function(data) {
//have to get the helpers as we are using this outside chart where it was declared
var helpers = Chart.helpers;
//Declare the extension of the default point, to cater for the options passed in to the constructor
this.PointClass = Chart.Point.extend({
strokeWidth: this.options.pointDotStrokeWidth,
radius: this.options.pointDotRadius,
display: this.options.pointDot,
hitDetectionRadius: this.options.pointHitDetectionRadius,
ctx: this.chart.ctx,
inRange: function(mouseX) {
return (Math.pow(mouseX - this.x, 2) < Math.pow(this.radius + this.hitDetectionRadius, 2));
}
});
this.datasets = [];
//Set up tooltip events on the chart
if (this.options.showTooltips) {
helpers.bindEvents(this, this.options.tooltipEvents, function(evt) {
var activePoints = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
this.eachPoints(function(point) {
point.restore(['fillColor', 'strokeColor']);
});
helpers.each(activePoints, function(activePoint) {
activePoint.fillColor = activePoint.highlightFill;
activePoint.strokeColor = activePoint.highlightStroke;
});
this.showTooltip(activePoints);
});
}
//Iterate through each of the datasets, and build this into a property of the chart
helpers.each(data.datasets, function(dataset) {
var datasetObject = {
label: dataset.label || null,
fillColor: dataset.fillColor,
strokeColor: dataset.strokeColor,
pointColor: dataset.pointColor,
pointStrokeColor: dataset.pointStrokeColor,
showTooltip: dataset.showTooltip,
points: []
};
this.datasets.push(datasetObject);
helpers.each(dataset.data, function(dataPoint, index) {
//Add a new point for each piece of data, passing any required data to draw.
datasetObject.points.push(new this.PointClass({
/*
* set wether to show the tooltip or not, left this as being able to be undfined
* and default to true
*/
showTooltip: dataset.showTooltip === undefined ? true : dataset.showTooltip,
value: dataPoint,
label: data.labels[index],
datasetLabel: dataset.label,
strokeColor: dataset.pointStrokeColor,
fillColor: dataset.pointColor,
highlightFill: dataset.pointHighlightFill || dataset.pointColor,
highlightStroke: dataset.pointHighlightStroke || dataset.pointStrokeColor
}));
}, this);
this.buildScale(data.labels);
this.eachPoints(function(point, index) {
helpers.extend(point, {
x: this.scale.calculateX(index),
y: this.scale.endPoint
});
point.save();
}, this);
}, this);
this.render();
},
/*
* need to edit how points at event works so it only uses points that we want to show the tool tip for
*/
getPointsAtEvent: function(e) {
//have to get the helpers as we are using this outside chart where it was declared
var helpers = Chart.helpers;
var pointsArray = [],
eventPosition = helpers.getRelativePosition(e);
helpers.each(this.datasets, function(dataset) {
helpers.each(dataset.points, function(point) {
if (point.inRange(eventPosition.x, eventPosition.y) && point.showTooltip) pointsArray.push(point);
});
}, this);
return pointsArray;
},
/*
* also need to change how the core showTooltip functions as otherwise, it trys to be helpful
* and grab any points it thinks also need to be displayed
*/
showTooltip: function(ChartElements, forceRedraw) {
//have to get the helpers as we are using this outside chart where it was declared
var helpers = Chart.helpers;
var each = helpers.each;
var indexOf = helpers.indexOf;
var min = helpers.min;
var max = helpers.min;
// Only redraw the chart if we've actually changed what we're hovering on.
if (typeof this.activeElements === 'undefined') this.activeElements = [];
var isChanged = (function(Elements) {
var changed = false;
if (Elements.length !== this.activeElements.length) {
changed = true;
return changed;
}
each(Elements, function(element, index) {
if (element !== this.activeElements[index]) {
changed = true;
}
}, this);
return changed;
}).call(this, ChartElements);
if (!isChanged && !forceRedraw) {
return;
} else {
this.activeElements = ChartElements;
}
this.draw();
if (ChartElements.length > 0) {
// If we have multiple datasets, show a MultiTooltip for all of the data points at that index
if (this.datasets && this.datasets.length > 1) {
var dataArray,
dataIndex;
for (var i = this.datasets.length - 1; i >= 0; i--) {
dataArray = this.datasets[i].points || this.datasets[i].bars || this.datasets[i].segments;
dataIndex = indexOf(dataArray, ChartElements[0]);
if (dataIndex !== -1) {
break;
}
}
var tooltipLabels = [],
tooltipColors = [],
medianPosition = (function(index) {
// Get all the points at that particular index
var Elements = [],
dataCollection,
xPositions = [],
yPositions = [],
xMax,
yMax,
xMin,
yMin;
helpers.each(this.datasets, function(dataset) {
dataCollection = dataset.points || dataset.bars || dataset.segments;
/*
*check to make sure we want to show the point
*/
if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue() && (dataCollection[dataIndex].showTooltip === undefined || dataCollection[dataIndex].showTooltip)) {
Elements.push(dataCollection[dataIndex]);
}
});
helpers.each(Elements, function(element) {
xPositions.push(element.x);
yPositions.push(element.y);
//Include any colour information about the element
tooltipLabels.push(helpers.template(this.options.multiTooltipTemplate, element));
tooltipColors.push({
fill: element._saved.fillColor || element.fillColor,
stroke: element._saved.strokeColor || element.strokeColor
});
}, this);
yMin = min(yPositions);
yMax = max(yPositions);
xMin = min(xPositions);
xMax = max(xPositions);
return {
x: (xMin > this.chart.width / 2) ? xMin : xMax,
y: (yMin + yMax) / 2
};
}).call(this, dataIndex);
new Chart.MultiTooltip({
x: medianPosition.x,
y: medianPosition.y,
xPadding: this.options.tooltipXPadding,
yPadding: this.options.tooltipYPadding,
xOffset: this.options.tooltipXOffset,
fillColor: this.options.tooltipFillColor,
textColor: this.options.tooltipFontColor,
fontFamily: this.options.tooltipFontFamily,
fontStyle: this.options.tooltipFontStyle,
fontSize: this.options.tooltipFontSize,
titleTextColor: this.options.tooltipTitleFontColor,
titleFontFamily: this.options.tooltipTitleFontFamily,
titleFontStyle: this.options.tooltipTitleFontStyle,
titleFontSize: this.options.tooltipTitleFontSize,
cornerRadius: this.options.tooltipCornerRadius,
labels: tooltipLabels,
legendColors: tooltipColors,
legendColorBackground: this.options.multiTooltipKeyBackground,
title: ChartElements[0].label,
chart: this.chart,
ctx: this.chart.ctx
}).draw();
} else {
each(ChartElements, function(Element) {
var tooltipPosition = Element.tooltipPosition();
new Chart.Tooltip({
x: Math.round(tooltipPosition.x),
y: Math.round(tooltipPosition.y),
xPadding: this.options.tooltipXPadding,
yPadding: this.options.tooltipYPadding,
fillColor: this.options.tooltipFillColor,
textColor: this.options.tooltipFontColor,
fontFamily: this.options.tooltipFontFamily,
fontStyle: this.options.tooltipFontStyle,
fontSize: this.options.tooltipFontSize,
caretHeight: this.options.tooltipCaretSize,
cornerRadius: this.options.tooltipCornerRadius,
text: template(this.options.tooltipTemplate, Element),
chart: this.chart
}).draw();
}, this);
}
}
return this;
},
});
var ctx = document.getElementById("chart").getContext("2d");
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.75)",
highlightStroke: "rgba(220,220,220,1)",
showTooltip: false, //TO USE JUST ADD THIS NEW OPTION ONLY REALLY NEEDS TO PRESENT IF SETTING TO FALSE
data: [15, 10, 10, 10, 10, 10, 10]
}, {
label: "My second dataset",
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.75)",
highlightStroke: "rgba(220,220,220,1)",
showTooltip: false, //TO USE JUST ADD THIS NEW OPTION ONLY REALLY NEEDS TO PRESENT IF SETTING TO FALSE
data: [100, 100, 100, 100, 100, 100, 100]
}, {
label: "My third dataset",
fillColor: "rgba(151,187,205,0.5)",
strokeColor: "rgba(151,187,205,0.8)",
highlightFill: "rgba(151,187,205,0.75)",
highlightStroke: "rgba(151,187,205,1)",
data: [28, 48, 40, 19, 86, 27, 90]
}]
};
var myBarChart = new Chart(ctx).LineTooltip(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js"></script>
<canvas id="chart" width="600px"></canvas>
and a fiddle if you find that easy to view http://jsfiddle.net/leighking2/1Lammwpt/