mirror of
https://github.com/chartjs/Chart.js.git
synced 2025-12-08 20:36:08 +00:00
Rough Tooltips for 'single' hoverMode
This commit is contained in:
parent
afb22d15ae
commit
15f724f146
@ -22,9 +22,11 @@
|
||||
var barChartData = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: 'Dataset 1',
|
||||
backgroundColor: "rgba(220,220,220,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: 'Dataset 2',
|
||||
backgroundColor: "rgba(151,187,205,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}]
|
||||
@ -34,7 +36,7 @@
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myBar = new Chart(ctx).Bar(barChartData, {
|
||||
responsive: true,
|
||||
hoverMode: 'bar',
|
||||
hoverMode: 'single',
|
||||
scaleBeginAtZero: false,
|
||||
});
|
||||
}
|
||||
|
||||
106
src/Chart.Bar.js
106
src/Chart.Bar.js
@ -34,14 +34,14 @@
|
||||
//Number - Spacing between data sets within X values
|
||||
barDatasetSpacing : 1,
|
||||
|
||||
//String - Hover mode for events
|
||||
hoverMode : 'bars', // 'bar', 'dataset'
|
||||
//String / Boolean - Hover mode for events.
|
||||
hoverMode : 'single', // 'label', 'dataset', 'false'
|
||||
|
||||
//Function - Custom hover handler
|
||||
onHover : null,
|
||||
|
||||
//Function - Custom hover handler
|
||||
hoverDuration : 400,
|
||||
hoverAnimationDuration : 400,
|
||||
|
||||
//String - A legend template
|
||||
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].backgroundColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
|
||||
@ -62,10 +62,10 @@
|
||||
|
||||
this.ScaleClass = Chart.Scale.extend({
|
||||
offsetGridLines : true,
|
||||
calculateBarX : function(datasetCount, datasetIndex, barIndex){
|
||||
calculateBarX : function(datasetCount, datasetIndex, elementIndex){
|
||||
//Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar
|
||||
var xWidth = this.calculateBaseWidth(),
|
||||
xAbsolute = this.calculateX(barIndex) - (xWidth/2),
|
||||
xAbsolute = this.calculateX(elementIndex) - (xWidth/2),
|
||||
barWidth = this.calculateBarWidth(datasetCount);
|
||||
|
||||
return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2;
|
||||
@ -116,61 +116,87 @@
|
||||
},
|
||||
onHover: function(e){
|
||||
|
||||
var active;
|
||||
|
||||
// If exiting chart
|
||||
if(e.type == 'mouseout'){
|
||||
return false;
|
||||
}
|
||||
if(this.options.hoverMode == 'bar'){
|
||||
active = this.getBarAtEvent(e);
|
||||
}
|
||||
else if(this.options.hoverMode == 'bars'){}
|
||||
|
||||
|
||||
// Remove styling for last active
|
||||
if(this.lastActive){
|
||||
if(this.options.hoverMode == 'bar'){
|
||||
this.lastActive.rectangle.backgroundColor = this.data.datasets[this.lastActive.datasetIndex].backgroundColor;
|
||||
this.lastActive.rectangle.borderColor = this.data.datasets[this.lastActive.datasetIndex].borderColor;
|
||||
this.lastActive.rectangle.borderWidth = 0;
|
||||
var active = function(){
|
||||
switch(this.options.hoverMode){
|
||||
case 'single':
|
||||
return this.getBarAtEvent(e);
|
||||
case 'label':
|
||||
return this.getBarsAtEvent(e);
|
||||
case 'dataset':
|
||||
return this.getDatasetAtEvent(e);
|
||||
default:
|
||||
return e;
|
||||
}
|
||||
}.call(this);
|
||||
|
||||
|
||||
// Remove styling for last active (even if it may still be active)
|
||||
if(this.lastActive){
|
||||
switch(this.options.hoverMode){
|
||||
case 'single':
|
||||
this.lastActive.element.backgroundColor = this.data.datasets[this.lastActive.datasetIndex].backgroundColor;
|
||||
this.lastActive.element.borderColor = this.data.datasets[this.lastActive.datasetIndex].borderColor;
|
||||
this.lastActive.element.borderWidth = 0;
|
||||
break;
|
||||
case 'label':
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// do nothing
|
||||
}
|
||||
else if(this.options.hoverMode == 'bars'){}
|
||||
}
|
||||
|
||||
// Custom Hover actions
|
||||
// On Hover hook
|
||||
if(this.options.onHover){
|
||||
this.options.onHover.call(this, active);
|
||||
}
|
||||
else if(active){
|
||||
// or default hover action
|
||||
if(this.options.hoverMode == 'bar'){
|
||||
active.rectangle.backgroundColor = this.data.datasets[active.datasetIndex].hoverBackgroundColor || Color(active.rectangle.backgroundColor).saturate(0.5).darken(0.25).rgbString();
|
||||
active.rectangle.borderColor = this.data.datasets[active.datasetIndex].hoverBorderColor || Color(active.rectangle.borderColor).saturate(0.5).darken(0.25).rgbString();
|
||||
|
||||
// Built in hover actions
|
||||
if(active && this.options.hoverMode){
|
||||
switch(this.options.hoverMode){
|
||||
case 'single':
|
||||
active.element.backgroundColor = this.data.datasets[active.datasetIndex].hoverBackgroundColor || helpers.color(active.element.backgroundColor).saturate(0.5).darken(0.25).rgbString();
|
||||
active.element.borderColor = this.data.datasets[active.datasetIndex].hoverBorderColor || helpers.color(active.element.borderColor).saturate(0.5).darken(0.25).rgbString();
|
||||
break;
|
||||
case 'label':
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// do nothing
|
||||
}
|
||||
else if(this.options.hoverMode == 'bars'){}
|
||||
|
||||
}
|
||||
|
||||
// Only animate for major events
|
||||
if(!this.animating){
|
||||
// If entering
|
||||
if(!this.lastActive && active){
|
||||
this.render(false, this.options.hoverDuration);
|
||||
this.render(false, this.options.hoverAnimationDuration);
|
||||
}
|
||||
|
||||
// If different bar
|
||||
if(this.lastActive && active && this.lastActive.rectangle !== active.rectangle){
|
||||
this.render(false, this.options.hoverDuration);
|
||||
// If different element
|
||||
if(this.lastActive && active && this.lastActive.element !== active.element){
|
||||
this.render(false, this.options.hoverAnimationDuration);
|
||||
}
|
||||
|
||||
// if Leaving
|
||||
if (this.lastActive && !active){
|
||||
this.render(false, this.options.hoverDuration);
|
||||
this.render(false, this.options.hoverAnimationDuration);
|
||||
}
|
||||
}
|
||||
|
||||
// Remember Last Active
|
||||
this.lastActive = active;
|
||||
|
||||
if (this.options.showTooltips){
|
||||
this.showTooltip(active);
|
||||
this.showTooltip(active, this.options.hoverMode);
|
||||
}
|
||||
},
|
||||
// Calculate the base point for the bar.
|
||||
@ -229,13 +255,13 @@
|
||||
var barsArray = [],
|
||||
eventPosition = helpers.getRelativePosition(e),
|
||||
datasetIterator = function(dataset){
|
||||
barsArray.push(dataset.metaData[barIndex]);
|
||||
barsArray.push(dataset.metaData[elementIndex]);
|
||||
},
|
||||
barIndex;
|
||||
elementIndex;
|
||||
|
||||
for (var datasetIndex = 0; datasetIndex < this.data.datasets.length; datasetIndex++) {
|
||||
for (barIndex = 0; barIndex < this.data.datasets[datasetIndex].metaData.length; barIndex++) {
|
||||
if (this.data.datasets[datasetIndex].metaData[barIndex].inRange(eventPosition.x,eventPosition.y)){
|
||||
for (elementIndex = 0; elementIndex < this.data.datasets[datasetIndex].metaData.length; elementIndex++) {
|
||||
if (this.data.datasets[datasetIndex].metaData[elementIndex].inRange(eventPosition.x,eventPosition.y)){
|
||||
helpers.each(this.data.datasets, datasetIterator);
|
||||
return barsArray;
|
||||
}
|
||||
@ -251,12 +277,12 @@
|
||||
var eventPosition = helpers.getRelativePosition(e);
|
||||
|
||||
for (var datasetIndex = 0; datasetIndex < this.data.datasets.length; ++datasetIndex) {
|
||||
for (var barIndex = 0; barIndex < this.data.datasets[datasetIndex].metaData.length; ++barIndex) {
|
||||
if (this.data.datasets[datasetIndex].metaData[barIndex].inRange(eventPosition.x, eventPosition.y)) {
|
||||
for (var elementIndex = 0; elementIndex < this.data.datasets[datasetIndex].metaData.length; ++elementIndex) {
|
||||
if (this.data.datasets[datasetIndex].metaData[elementIndex].inRange(eventPosition.x, eventPosition.y)) {
|
||||
bar = {
|
||||
rectangle : this.data.datasets[datasetIndex].metaData[barIndex],
|
||||
element : this.data.datasets[datasetIndex].metaData[elementIndex],
|
||||
datasetIndex : datasetIndex,
|
||||
barIndex : barIndex,
|
||||
elementIndex : elementIndex,
|
||||
};
|
||||
return bar;
|
||||
}
|
||||
|
||||
@ -883,9 +883,21 @@
|
||||
ctx.lineTo(x, y + radius);
|
||||
ctx.quadraticCurveTo(x, y, x + radius, y);
|
||||
ctx.closePath();
|
||||
},
|
||||
color = helpers.color = function(color){
|
||||
if(!window.Color){
|
||||
console.log('Color.js not found!');
|
||||
return color;
|
||||
}
|
||||
return window.Color(color);
|
||||
},
|
||||
isArray = helpers.isArray = function(obj){
|
||||
if (!Array.isArray) {
|
||||
return Object.prototype.toString.call(arg) === '[object Array]';
|
||||
}
|
||||
return Array.isArray(obj);
|
||||
};
|
||||
|
||||
|
||||
//Store a reference to each instance - allowing us to globally resize chart instances on window resize.
|
||||
//Destroy method on the chart will remove the instance of the chart from this reference.
|
||||
Chart.instances = {};
|
||||
@ -988,45 +1000,46 @@
|
||||
|
||||
delete Chart.instances[this.id];
|
||||
},
|
||||
showTooltip : function(ChartElements, forceRedraw){
|
||||
// Only redraw the chart if we've actually changed what we're hovering on.
|
||||
if (typeof this.activeElements === 'undefined') this.activeElements = [];
|
||||
showTooltip : function(elements, hoverMode){
|
||||
|
||||
var isChanged = (function(Elements){
|
||||
var changed = false;
|
||||
|
||||
if (Elements.length !== this.activeElements.length){
|
||||
changed = true;
|
||||
return changed;
|
||||
// Hide if no elements
|
||||
if(!elements){
|
||||
if(this.options.customTooltips){
|
||||
this.options.customTooltips(false);
|
||||
}
|
||||
if(!this.animating){
|
||||
this.render(false, this.options.hoverAnimationDuration);
|
||||
}
|
||||
|
||||
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(this.options.customTooltips){
|
||||
this.options.customTooltips(false);
|
||||
}
|
||||
if (ChartElements.length > 0){
|
||||
// If we have multiple datasets, show a MultiTooltip for all of the data points at that index
|
||||
if (this.data.datasets && this.data.datasets.length > 1) {
|
||||
|
||||
switch(hoverMode){
|
||||
case 'single':
|
||||
var tooltipPosition = elements.element.tooltipPosition();
|
||||
new Chart.Tooltip({
|
||||
x: Math.round(tooltipPosition.x),
|
||||
y: Math.round(tooltipPosition.y),
|
||||
xPadding: this.options.tooltipXPadding,
|
||||
yPadding: this.options.tooltipYPadding,
|
||||
backgroundColor: this.options.tooltipBackgroundColor,
|
||||
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, elements.element),
|
||||
chart: this.chart,
|
||||
custom: this.options.customTooltips
|
||||
}).draw();
|
||||
break;
|
||||
case 'label':
|
||||
var dataArray,
|
||||
dataIndex;
|
||||
|
||||
for (var i = this.data.datasets.length - 1; i >= 0; i--) {
|
||||
dataArray = this.data.datasets[i].metaData;
|
||||
dataIndex = indexOf(dataArray, ChartElements[0]);
|
||||
dataIndex = indexOf(dataArray, elements[0]);
|
||||
if (dataIndex !== -1){
|
||||
break;
|
||||
}
|
||||
@ -1096,34 +1109,17 @@
|
||||
labels: tooltipLabels,
|
||||
legendColors: tooltipColors,
|
||||
legendColorBackground : this.options.multiTooltipKeyBackground,
|
||||
title: ChartElements[0].label,
|
||||
title: elements[0].label,
|
||||
chart: this.chart,
|
||||
ctx: this.chart.ctx,
|
||||
custom: this.options.customTooltips
|
||||
}).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,
|
||||
backgroundColor: this.options.tooltipBackgroundColor,
|
||||
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,
|
||||
custom: this.options.customTooltips
|
||||
}).draw();
|
||||
}, this);
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
toBase64Image : function(){
|
||||
@ -1206,7 +1202,7 @@
|
||||
// Color transitions if possible
|
||||
if(typeof value === 'string'){
|
||||
try{
|
||||
var color = Color(this._start[key]).mix(Color(this[key]), ease);
|
||||
var color = helpers.color(this._start[key]).mix(helpers.color(this[key]), ease);
|
||||
this._vm[key] = color.rgbString();
|
||||
} catch(err){
|
||||
this._vm[key] = value;
|
||||
@ -1392,7 +1388,21 @@
|
||||
{
|
||||
return (chartX >= this.x - this.width / 2 && chartX <= this.x + this.width / 2) && (chartY >= this.base && chartY <= this.y);
|
||||
}
|
||||
}
|
||||
},
|
||||
tooltipPosition : function(){
|
||||
if (this.y < this.base){
|
||||
return {
|
||||
x : this.x,
|
||||
y : this.y
|
||||
};
|
||||
}
|
||||
else{
|
||||
return {
|
||||
x : this.x,
|
||||
y : this.base
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Chart.Animation = Chart.Element.extend({
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user