mirror of
https://github.com/chartjs/Chart.js.git
synced 2025-12-08 20:36:08 +00:00
Fix/3061 (#3446)
Solve weird animation issues with the tooltip. The optimization in Chart.Element.transition when the animation finishes to set `_view = _model` caused problems during update because we were using `helpers.extend` all over the place. I changed to code so that we regenerate the model variable rather than continuously extending the old version. I also removed unnecessary tooltip reinitializations from the controller which should improve overall performance during interaction.
This commit is contained in:
parent
65a06e4735
commit
d21a853f30
@ -630,6 +630,7 @@ module.exports = function(Chart) {
|
||||
_data: me.data,
|
||||
_options: me.options.tooltips
|
||||
}, me);
|
||||
me.tooltip.initialize();
|
||||
},
|
||||
|
||||
bindEvents: function() {
|
||||
@ -711,14 +712,10 @@ module.exports = function(Chart) {
|
||||
|
||||
// Built in Tooltips
|
||||
if (tooltipsOptions.enabled || tooltipsOptions.custom) {
|
||||
tooltip.initialize();
|
||||
tooltip._active = me.tooltipActive;
|
||||
tooltip.update(true);
|
||||
}
|
||||
|
||||
// Hover animations
|
||||
tooltip.pivot();
|
||||
|
||||
if (!me.animating) {
|
||||
// If entering, leaving, or changing elements, animate the change via pivot
|
||||
if (!helpers.arrayEquals(me.active, me.lastActive) ||
|
||||
@ -728,6 +725,7 @@ module.exports = function(Chart) {
|
||||
|
||||
if (tooltipsOptions.enabled || tooltipsOptions.custom) {
|
||||
tooltip.update(true);
|
||||
tooltip.pivot();
|
||||
}
|
||||
|
||||
// We only need to render at this point. Updating will cause scales to be
|
||||
|
||||
@ -33,8 +33,6 @@ module.exports = function(Chart) {
|
||||
footerAlign: 'left',
|
||||
yPadding: 6,
|
||||
xPadding: 6,
|
||||
yAlign: 'center',
|
||||
xAlign: 'center',
|
||||
caretSize: 5,
|
||||
cornerRadius: 6,
|
||||
multiKeyBackground: '#fff',
|
||||
@ -156,56 +154,249 @@ module.exports = function(Chart) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to get the reset model for the tooltip
|
||||
* @param tooltipOpts {Object} the tooltip options
|
||||
*/
|
||||
function getBaseModel(tooltipOpts) {
|
||||
var globalDefaults = Chart.defaults.global;
|
||||
var getValueOrDefault = helpers.getValueOrDefault;
|
||||
|
||||
return {
|
||||
// Positioning
|
||||
xPadding: tooltipOpts.xPadding,
|
||||
yPadding: tooltipOpts.yPadding,
|
||||
xAlign: tooltipOpts.xAlign,
|
||||
yAlign: tooltipOpts.yAlign,
|
||||
|
||||
// Body
|
||||
bodyFontColor: tooltipOpts.bodyFontColor,
|
||||
_bodyFontFamily: getValueOrDefault(tooltipOpts.bodyFontFamily, globalDefaults.defaultFontFamily),
|
||||
_bodyFontStyle: getValueOrDefault(tooltipOpts.bodyFontStyle, globalDefaults.defaultFontStyle),
|
||||
_bodyAlign: tooltipOpts.bodyAlign,
|
||||
bodyFontSize: getValueOrDefault(tooltipOpts.bodyFontSize, globalDefaults.defaultFontSize),
|
||||
bodySpacing: tooltipOpts.bodySpacing,
|
||||
|
||||
// Title
|
||||
titleFontColor: tooltipOpts.titleFontColor,
|
||||
_titleFontFamily: getValueOrDefault(tooltipOpts.titleFontFamily, globalDefaults.defaultFontFamily),
|
||||
_titleFontStyle: getValueOrDefault(tooltipOpts.titleFontStyle, globalDefaults.defaultFontStyle),
|
||||
titleFontSize: getValueOrDefault(tooltipOpts.titleFontSize, globalDefaults.defaultFontSize),
|
||||
_titleAlign: tooltipOpts.titleAlign,
|
||||
titleSpacing: tooltipOpts.titleSpacing,
|
||||
titleMarginBottom: tooltipOpts.titleMarginBottom,
|
||||
|
||||
// Footer
|
||||
footerFontColor: tooltipOpts.footerFontColor,
|
||||
_footerFontFamily: getValueOrDefault(tooltipOpts.footerFontFamily, globalDefaults.defaultFontFamily),
|
||||
_footerFontStyle: getValueOrDefault(tooltipOpts.footerFontStyle, globalDefaults.defaultFontStyle),
|
||||
footerFontSize: getValueOrDefault(tooltipOpts.footerFontSize, globalDefaults.defaultFontSize),
|
||||
_footerAlign: tooltipOpts.footerAlign,
|
||||
footerSpacing: tooltipOpts.footerSpacing,
|
||||
footerMarginTop: tooltipOpts.footerMarginTop,
|
||||
|
||||
// Appearance
|
||||
caretSize: tooltipOpts.caretSize,
|
||||
cornerRadius: tooltipOpts.cornerRadius,
|
||||
backgroundColor: tooltipOpts.backgroundColor,
|
||||
opacity: 0,
|
||||
legendColorBackground: tooltipOpts.multiKeyBackground,
|
||||
displayColors: tooltipOpts.displayColors
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of the tooltip
|
||||
*/
|
||||
function getTooltipSize(tooltip, model) {
|
||||
var ctx = tooltip._chart.ctx;
|
||||
|
||||
var height = model.yPadding * 2; // Tooltip Padding
|
||||
var width = 0;
|
||||
|
||||
// Count of all lines in the body
|
||||
var body = model.body;
|
||||
var combinedBodyLength = body.reduce(function(count, bodyItem) {
|
||||
return count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length;
|
||||
}, 0);
|
||||
combinedBodyLength += model.beforeBody.length + model.afterBody.length;
|
||||
|
||||
var titleLineCount = model.title.length;
|
||||
var footerLineCount = model.footer.length;
|
||||
var titleFontSize = model.titleFontSize,
|
||||
bodyFontSize = model.bodyFontSize,
|
||||
footerFontSize = model.footerFontSize;
|
||||
|
||||
height += titleLineCount * titleFontSize; // Title Lines
|
||||
height += titleLineCount ? (titleLineCount - 1) * model.titleSpacing : 0; // Title Line Spacing
|
||||
height += titleLineCount ? model.titleMarginBottom : 0; // Title's bottom Margin
|
||||
height += combinedBodyLength * bodyFontSize; // Body Lines
|
||||
height += combinedBodyLength ? (combinedBodyLength - 1) * model.bodySpacing : 0; // Body Line Spacing
|
||||
height += footerLineCount ? model.footerMarginTop : 0; // Footer Margin
|
||||
height += footerLineCount * (footerFontSize); // Footer Lines
|
||||
height += footerLineCount ? (footerLineCount - 1) * model.footerSpacing : 0; // Footer Line Spacing
|
||||
|
||||
// Title width
|
||||
var widthPadding = 0;
|
||||
var maxLineWidth = function(line) {
|
||||
width = Math.max(width, ctx.measureText(line).width + widthPadding);
|
||||
};
|
||||
|
||||
ctx.font = helpers.fontString(titleFontSize, model._titleFontStyle, model._titleFontFamily);
|
||||
helpers.each(model.title, maxLineWidth);
|
||||
|
||||
// Body width
|
||||
ctx.font = helpers.fontString(bodyFontSize, model._bodyFontStyle, model._bodyFontFamily);
|
||||
helpers.each(model.beforeBody.concat(model.afterBody), maxLineWidth);
|
||||
|
||||
// Body lines may include some extra width due to the color box
|
||||
widthPadding = model.displayColors ? (bodyFontSize + 2) : 0;
|
||||
helpers.each(body, function(bodyItem) {
|
||||
helpers.each(bodyItem.before, maxLineWidth);
|
||||
helpers.each(bodyItem.lines, maxLineWidth);
|
||||
helpers.each(bodyItem.after, maxLineWidth);
|
||||
});
|
||||
|
||||
// Reset back to 0
|
||||
widthPadding = 0;
|
||||
|
||||
// Footer width
|
||||
ctx.font = helpers.fontString(footerFontSize, model._footerFontStyle, model._footerFontFamily);
|
||||
helpers.each(model.footer, maxLineWidth);
|
||||
|
||||
// Add padding
|
||||
width += 2 * model.xPadding;
|
||||
|
||||
return {
|
||||
width: width,
|
||||
height: height
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to get the alignment of a tooltip given the size
|
||||
*/
|
||||
function determineAlignment(tooltip, size) {
|
||||
var model = tooltip._model;
|
||||
var chart = tooltip._chart;
|
||||
var chartArea = tooltip._chartInstance.chartArea;
|
||||
var xAlign = 'center';
|
||||
var yAlign = 'center';
|
||||
|
||||
if (model.y < size.height) {
|
||||
yAlign = 'top';
|
||||
} else if (model.y > (chart.height - size.height)) {
|
||||
yAlign = 'bottom';
|
||||
}
|
||||
|
||||
var lf, rf; // functions to determine left, right alignment
|
||||
var olf, orf; // functions to determine if left/right alignment causes tooltip to go outside chart
|
||||
var yf; // function to get the y alignment if the tooltip goes outside of the left or right edges
|
||||
var midX = (chartArea.left + chartArea.right) / 2;
|
||||
var midY = (chartArea.top + chartArea.bottom) / 2;
|
||||
|
||||
if (yAlign === 'center') {
|
||||
lf = function(x) {
|
||||
return x <= midX;
|
||||
};
|
||||
rf = function(x) {
|
||||
return x > midX;
|
||||
};
|
||||
} else {
|
||||
lf = function(x) {
|
||||
return x <= (size.width / 2);
|
||||
};
|
||||
rf = function(x) {
|
||||
return x >= (chart.width - (size.width / 2));
|
||||
};
|
||||
}
|
||||
|
||||
olf = function(x) {
|
||||
return x + size.width > chart.width;
|
||||
};
|
||||
orf = function(x) {
|
||||
return x - size.width < 0;
|
||||
};
|
||||
yf = function(y) {
|
||||
return y <= midY ? 'top' : 'bottom';
|
||||
};
|
||||
|
||||
if (lf(model.x)) {
|
||||
xAlign = 'left';
|
||||
|
||||
// Is tooltip too wide and goes over the right side of the chart.?
|
||||
if (olf(model.x)) {
|
||||
xAlign = 'center';
|
||||
yAlign = yf(model.y);
|
||||
}
|
||||
} else if (rf(model.x)) {
|
||||
xAlign = 'right';
|
||||
|
||||
// Is tooltip too wide and goes outside left edge of canvas?
|
||||
if (orf(model.x)) {
|
||||
xAlign = 'center';
|
||||
yAlign = yf(model.y);
|
||||
}
|
||||
}
|
||||
|
||||
var opts = tooltip._options;
|
||||
return {
|
||||
xAlign: opts.xAlign ? opts.xAlign : xAlign,
|
||||
yAlign: opts.yAlign ? opts.yAlign : yAlign
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @Helper to get the location a tooltiop needs to be placed at given the initial position (via the vm) and the size and alignment
|
||||
*/
|
||||
function getBackgroundPoint(vm, size, alignment) {
|
||||
// Background Position
|
||||
var x = vm.x;
|
||||
var y = vm.y;
|
||||
|
||||
var caretSize = vm.caretSize,
|
||||
caretPadding = vm.caretPadding,
|
||||
cornerRadius = vm.cornerRadius,
|
||||
xAlign = alignment.xAlign,
|
||||
yAlign = alignment.yAlign,
|
||||
paddingAndSize = caretSize + caretPadding,
|
||||
radiusAndPadding = cornerRadius + caretPadding;
|
||||
|
||||
if (xAlign === 'right') {
|
||||
x -= size.width;
|
||||
} else if (xAlign === 'center') {
|
||||
x -= (size.width / 2);
|
||||
}
|
||||
|
||||
if (yAlign === 'top') {
|
||||
y += paddingAndSize;
|
||||
} else if (yAlign === 'bottom') {
|
||||
y -= size.height + paddingAndSize;
|
||||
} else {
|
||||
y -= (size.height / 2);
|
||||
}
|
||||
|
||||
if (yAlign === 'center') {
|
||||
if (xAlign === 'left') {
|
||||
x += paddingAndSize;
|
||||
} else if (xAlign === 'right') {
|
||||
x -= paddingAndSize;
|
||||
}
|
||||
} else if (xAlign === 'left') {
|
||||
x -= radiusAndPadding;
|
||||
} else if (xAlign === 'right') {
|
||||
x += radiusAndPadding;
|
||||
}
|
||||
|
||||
return {
|
||||
x: x,
|
||||
y: y
|
||||
};
|
||||
}
|
||||
|
||||
Chart.Tooltip = Chart.Element.extend({
|
||||
initialize: function() {
|
||||
var me = this;
|
||||
var globalDefaults = Chart.defaults.global;
|
||||
var tooltipOpts = me._options;
|
||||
var getValueOrDefault = helpers.getValueOrDefault;
|
||||
|
||||
helpers.extend(me, {
|
||||
_model: {
|
||||
// Positioning
|
||||
xPadding: tooltipOpts.xPadding,
|
||||
yPadding: tooltipOpts.yPadding,
|
||||
xAlign: tooltipOpts.xAlign,
|
||||
yAlign: tooltipOpts.yAlign,
|
||||
|
||||
// Body
|
||||
bodyFontColor: tooltipOpts.bodyFontColor,
|
||||
_bodyFontFamily: getValueOrDefault(tooltipOpts.bodyFontFamily, globalDefaults.defaultFontFamily),
|
||||
_bodyFontStyle: getValueOrDefault(tooltipOpts.bodyFontStyle, globalDefaults.defaultFontStyle),
|
||||
_bodyAlign: tooltipOpts.bodyAlign,
|
||||
bodyFontSize: getValueOrDefault(tooltipOpts.bodyFontSize, globalDefaults.defaultFontSize),
|
||||
bodySpacing: tooltipOpts.bodySpacing,
|
||||
|
||||
// Title
|
||||
titleFontColor: tooltipOpts.titleFontColor,
|
||||
_titleFontFamily: getValueOrDefault(tooltipOpts.titleFontFamily, globalDefaults.defaultFontFamily),
|
||||
_titleFontStyle: getValueOrDefault(tooltipOpts.titleFontStyle, globalDefaults.defaultFontStyle),
|
||||
titleFontSize: getValueOrDefault(tooltipOpts.titleFontSize, globalDefaults.defaultFontSize),
|
||||
_titleAlign: tooltipOpts.titleAlign,
|
||||
titleSpacing: tooltipOpts.titleSpacing,
|
||||
titleMarginBottom: tooltipOpts.titleMarginBottom,
|
||||
|
||||
// Footer
|
||||
footerFontColor: tooltipOpts.footerFontColor,
|
||||
_footerFontFamily: getValueOrDefault(tooltipOpts.footerFontFamily, globalDefaults.defaultFontFamily),
|
||||
_footerFontStyle: getValueOrDefault(tooltipOpts.footerFontStyle, globalDefaults.defaultFontStyle),
|
||||
footerFontSize: getValueOrDefault(tooltipOpts.footerFontSize, globalDefaults.defaultFontSize),
|
||||
_footerAlign: tooltipOpts.footerAlign,
|
||||
footerSpacing: tooltipOpts.footerSpacing,
|
||||
footerMarginTop: tooltipOpts.footerMarginTop,
|
||||
|
||||
// Appearance
|
||||
caretSize: tooltipOpts.caretSize,
|
||||
cornerRadius: tooltipOpts.cornerRadius,
|
||||
backgroundColor: tooltipOpts.backgroundColor,
|
||||
opacity: 0,
|
||||
legendColorBackground: tooltipOpts.multiKeyBackground,
|
||||
displayColors: tooltipOpts.displayColors
|
||||
}
|
||||
});
|
||||
this._model = getBaseModel(this._options);
|
||||
},
|
||||
|
||||
// Get the title
|
||||
@ -282,12 +473,31 @@ module.exports = function(Chart) {
|
||||
update: function(changed) {
|
||||
var me = this;
|
||||
var opts = me._options;
|
||||
var model = me._model;
|
||||
|
||||
// Need to regenerate the model because its faster than using extend and it is necessary due to the optimization in Chart.Element.transition
|
||||
// that does _view = _model if ease === 1. This causes the 2nd tooltip update to set properties in both the view and model at the same time
|
||||
// which breaks any animations.
|
||||
var existingModel = me._model;
|
||||
var model = me._model = getBaseModel(opts);
|
||||
var active = me._active;
|
||||
|
||||
var data = me._data;
|
||||
var chartInstance = me._chartInstance;
|
||||
|
||||
// In the case where active.length === 0 we need to keep these at existing values for good animations
|
||||
var alignment = {
|
||||
xAlign: existingModel.xAlign,
|
||||
yAlign: existingModel.yAlign
|
||||
};
|
||||
var backgroundPoint = {
|
||||
x: existingModel.x,
|
||||
y: existingModel.y
|
||||
};
|
||||
var tooltipSize = {
|
||||
width: existingModel.width,
|
||||
height: existingModel.height
|
||||
};
|
||||
|
||||
var i, len;
|
||||
|
||||
if (active.length) {
|
||||
@ -314,201 +524,42 @@ module.exports = function(Chart) {
|
||||
});
|
||||
|
||||
// Build the Text Lines
|
||||
helpers.extend(model, {
|
||||
title: me.getTitle(tooltipItems, data),
|
||||
beforeBody: me.getBeforeBody(tooltipItems, data),
|
||||
body: me.getBody(tooltipItems, data),
|
||||
afterBody: me.getAfterBody(tooltipItems, data),
|
||||
footer: me.getFooter(tooltipItems, data),
|
||||
x: Math.round(tooltipPosition.x),
|
||||
y: Math.round(tooltipPosition.y),
|
||||
caretPadding: helpers.getValueOrDefault(tooltipPosition.padding, 2),
|
||||
labelColors: labelColors
|
||||
});
|
||||
model.title = me.getTitle(tooltipItems, data);
|
||||
model.beforeBody = me.getBeforeBody(tooltipItems, data);
|
||||
model.body = me.getBody(tooltipItems, data);
|
||||
model.afterBody = me.getAfterBody(tooltipItems, data);
|
||||
model.footer = me.getFooter(tooltipItems, data);
|
||||
|
||||
// We need to determine alignment of
|
||||
var tooltipSize = me.getTooltipSize(model);
|
||||
me.determineAlignment(tooltipSize); // Smart Tooltip placement to stay on the canvas
|
||||
// Initial positioning and colors
|
||||
model.x = Math.round(tooltipPosition.x);
|
||||
model.y = Math.round(tooltipPosition.y);
|
||||
model.caretPadding = helpers.getValueOrDefault(tooltipPosition.padding, 2);
|
||||
model.labelColors = labelColors;
|
||||
|
||||
helpers.extend(model, me.getBackgroundPoint(model, tooltipSize));
|
||||
// We need to determine alignment of the tooltip
|
||||
tooltipSize = getTooltipSize(this, model);
|
||||
alignment = determineAlignment(this, tooltipSize);
|
||||
// Final Size and Position
|
||||
backgroundPoint = getBackgroundPoint(model, tooltipSize, alignment);
|
||||
} else {
|
||||
me._model.opacity = 0;
|
||||
model.opacity = 0;
|
||||
}
|
||||
|
||||
model.xAlign = alignment.xAlign;
|
||||
model.yAlign = alignment.yAlign;
|
||||
model.x = backgroundPoint.x;
|
||||
model.y = backgroundPoint.y;
|
||||
model.width = tooltipSize.width;
|
||||
model.height = tooltipSize.height;
|
||||
|
||||
me._model = model;
|
||||
|
||||
if (changed && opts.custom) {
|
||||
opts.custom.call(me, model);
|
||||
}
|
||||
|
||||
return me;
|
||||
},
|
||||
getTooltipSize: function(vm) {
|
||||
var ctx = this._chart.ctx;
|
||||
|
||||
var size = {
|
||||
height: vm.yPadding * 2, // Tooltip Padding
|
||||
width: 0
|
||||
};
|
||||
|
||||
// Count of all lines in the body
|
||||
var body = vm.body;
|
||||
var combinedBodyLength = body.reduce(function(count, bodyItem) {
|
||||
return count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length;
|
||||
}, 0);
|
||||
combinedBodyLength += vm.beforeBody.length + vm.afterBody.length;
|
||||
|
||||
var titleLineCount = vm.title.length;
|
||||
var footerLineCount = vm.footer.length;
|
||||
var titleFontSize = vm.titleFontSize,
|
||||
bodyFontSize = vm.bodyFontSize,
|
||||
footerFontSize = vm.footerFontSize;
|
||||
|
||||
size.height += titleLineCount * titleFontSize; // Title Lines
|
||||
size.height += titleLineCount ? (titleLineCount - 1) * vm.titleSpacing : 0; // Title Line Spacing
|
||||
size.height += titleLineCount ? vm.titleMarginBottom : 0; // Title's bottom Margin
|
||||
size.height += combinedBodyLength * bodyFontSize; // Body Lines
|
||||
size.height += combinedBodyLength ? (combinedBodyLength - 1) * vm.bodySpacing : 0; // Body Line Spacing
|
||||
size.height += footerLineCount ? vm.footerMarginTop : 0; // Footer Margin
|
||||
size.height += footerLineCount * (footerFontSize); // Footer Lines
|
||||
size.height += footerLineCount ? (footerLineCount - 1) * vm.footerSpacing : 0; // Footer Line Spacing
|
||||
|
||||
// Title width
|
||||
var widthPadding = 0;
|
||||
var maxLineWidth = function(line) {
|
||||
size.width = Math.max(size.width, ctx.measureText(line).width + widthPadding);
|
||||
};
|
||||
|
||||
ctx.font = helpers.fontString(titleFontSize, vm._titleFontStyle, vm._titleFontFamily);
|
||||
helpers.each(vm.title, maxLineWidth);
|
||||
|
||||
// Body width
|
||||
ctx.font = helpers.fontString(bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily);
|
||||
helpers.each(vm.beforeBody.concat(vm.afterBody), maxLineWidth);
|
||||
|
||||
// Body lines may include some extra width due to the color box
|
||||
widthPadding = vm.displayColors ? (bodyFontSize + 2) : 0;
|
||||
helpers.each(body, function(bodyItem) {
|
||||
helpers.each(bodyItem.before, maxLineWidth);
|
||||
helpers.each(bodyItem.lines, maxLineWidth);
|
||||
helpers.each(bodyItem.after, maxLineWidth);
|
||||
});
|
||||
|
||||
// Reset back to 0
|
||||
widthPadding = 0;
|
||||
|
||||
// Footer width
|
||||
ctx.font = helpers.fontString(footerFontSize, vm._footerFontStyle, vm._footerFontFamily);
|
||||
helpers.each(vm.footer, maxLineWidth);
|
||||
|
||||
// Add padding
|
||||
size.width += 2 * vm.xPadding;
|
||||
|
||||
return size;
|
||||
},
|
||||
determineAlignment: function(size) {
|
||||
var me = this;
|
||||
var model = me._model;
|
||||
var chart = me._chart;
|
||||
var chartArea = me._chartInstance.chartArea;
|
||||
|
||||
if (model.y < size.height) {
|
||||
model.yAlign = 'top';
|
||||
} else if (model.y > (chart.height - size.height)) {
|
||||
model.yAlign = 'bottom';
|
||||
}
|
||||
|
||||
var lf, rf; // functions to determine left, right alignment
|
||||
var olf, orf; // functions to determine if left/right alignment causes tooltip to go outside chart
|
||||
var yf; // function to get the y alignment if the tooltip goes outside of the left or right edges
|
||||
var midX = (chartArea.left + chartArea.right) / 2;
|
||||
var midY = (chartArea.top + chartArea.bottom) / 2;
|
||||
|
||||
if (model.yAlign === 'center') {
|
||||
lf = function(x) {
|
||||
return x <= midX;
|
||||
};
|
||||
rf = function(x) {
|
||||
return x > midX;
|
||||
};
|
||||
} else {
|
||||
lf = function(x) {
|
||||
return x <= (size.width / 2);
|
||||
};
|
||||
rf = function(x) {
|
||||
return x >= (chart.width - (size.width / 2));
|
||||
};
|
||||
}
|
||||
|
||||
olf = function(x) {
|
||||
return x + size.width > chart.width;
|
||||
};
|
||||
orf = function(x) {
|
||||
return x - size.width < 0;
|
||||
};
|
||||
yf = function(y) {
|
||||
return y <= midY ? 'top' : 'bottom';
|
||||
};
|
||||
|
||||
if (lf(model.x)) {
|
||||
model.xAlign = 'left';
|
||||
|
||||
// Is tooltip too wide and goes over the right side of the chart.?
|
||||
if (olf(model.x)) {
|
||||
model.xAlign = 'center';
|
||||
model.yAlign = yf(model.y);
|
||||
}
|
||||
} else if (rf(model.x)) {
|
||||
model.xAlign = 'right';
|
||||
|
||||
// Is tooltip too wide and goes outside left edge of canvas?
|
||||
if (orf(model.x)) {
|
||||
model.xAlign = 'center';
|
||||
model.yAlign = yf(model.y);
|
||||
}
|
||||
}
|
||||
},
|
||||
getBackgroundPoint: function(vm, size) {
|
||||
// Background Position
|
||||
var pt = {
|
||||
x: vm.x,
|
||||
y: vm.y
|
||||
};
|
||||
|
||||
var caretSize = vm.caretSize,
|
||||
caretPadding = vm.caretPadding,
|
||||
cornerRadius = vm.cornerRadius,
|
||||
xAlign = vm.xAlign,
|
||||
yAlign = vm.yAlign,
|
||||
paddingAndSize = caretSize + caretPadding,
|
||||
radiusAndPadding = cornerRadius + caretPadding;
|
||||
|
||||
if (xAlign === 'right') {
|
||||
pt.x -= size.width;
|
||||
} else if (xAlign === 'center') {
|
||||
pt.x -= (size.width / 2);
|
||||
}
|
||||
|
||||
if (yAlign === 'top') {
|
||||
pt.y += paddingAndSize;
|
||||
} else if (yAlign === 'bottom') {
|
||||
pt.y -= size.height + paddingAndSize;
|
||||
} else {
|
||||
pt.y -= (size.height / 2);
|
||||
}
|
||||
|
||||
if (yAlign === 'center') {
|
||||
if (xAlign === 'left') {
|
||||
pt.x += paddingAndSize;
|
||||
} else if (xAlign === 'right') {
|
||||
pt.x -= paddingAndSize;
|
||||
}
|
||||
} else if (xAlign === 'left') {
|
||||
pt.x -= radiusAndPadding;
|
||||
} else if (xAlign === 'right') {
|
||||
pt.x += radiusAndPadding;
|
||||
}
|
||||
|
||||
return pt;
|
||||
},
|
||||
drawCaret: function(tooltipPoint, size, opacity) {
|
||||
var vm = this._view;
|
||||
var ctx = this._chart.ctx;
|
||||
@ -687,7 +738,10 @@ module.exports = function(Chart) {
|
||||
return;
|
||||
}
|
||||
|
||||
var tooltipSize = this.getTooltipSize(vm);
|
||||
var tooltipSize = {
|
||||
width: vm.width,
|
||||
height: vm.height
|
||||
};
|
||||
var pt = {
|
||||
x: vm.x,
|
||||
y: vm.y
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user