Skip to content

Commit

Permalink
Refactor tooltip mergeOpacity calls and support CanvasPattern and Can…
Browse files Browse the repository at this point in the history
…vasGradient
  • Loading branch information
nagix committed Nov 29, 2018
1 parent d6ac7d8 commit 93152df
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 25 deletions.
47 changes: 22 additions & 25 deletions src/core/core.tooltip.js
Expand Up @@ -168,14 +168,6 @@ var positioners = {
}
};

/**
* Helper method to merge the opacity into a color
*/
function mergeOpacity(colorString, opacity) {
var color = helpers.color(colorString);
return color.alpha(opacity * color.alpha()).rgbaString();
}

// Helper to push or concat based on if the 2nd parameter is an array or not
function pushOrConcat(base, toPush) {
if (toPush) {
Expand Down Expand Up @@ -734,7 +726,7 @@ var exports = module.exports = Element.extend({
return {x1: x1, x2: x2, x3: x3, y1: y1, y2: y2, y3: y3};
},

drawTitle: function(pt, vm, ctx, opacity) {
drawTitle: function(pt, vm, ctx) {
var title = vm.title;

if (title.length) {
Expand All @@ -744,7 +736,7 @@ var exports = module.exports = Element.extend({
var titleFontSize = vm.titleFontSize;
var titleSpacing = vm.titleSpacing;

ctx.fillStyle = mergeOpacity(vm.titleFontColor, opacity);
ctx.fillStyle = vm.titleFontColor;
ctx.font = helpers.fontString(titleFontSize, vm._titleFontStyle, vm._titleFontFamily);

var i, len;
Expand All @@ -759,7 +751,7 @@ var exports = module.exports = Element.extend({
}
},

drawBody: function(pt, vm, ctx, opacity) {
drawBody: function(pt, vm, ctx) {
var bodyFontSize = vm.bodyFontSize;
var bodySpacing = vm.bodySpacing;
var body = vm.body;
Expand All @@ -776,32 +768,32 @@ var exports = module.exports = Element.extend({
};

// Before body lines
ctx.fillStyle = mergeOpacity(vm.bodyFontColor, opacity);
ctx.fillStyle = vm.bodyFontColor;
helpers.each(vm.beforeBody, fillLineOfText);

var drawColorBoxes = vm.displayColors;
xLinePadding = drawColorBoxes ? (bodyFontSize + 2) : 0;

// Draw body lines now
helpers.each(body, function(bodyItem, i) {
var textColor = mergeOpacity(vm.labelTextColors[i], opacity);
var textColor = vm.labelTextColors[i];
ctx.fillStyle = textColor;
helpers.each(bodyItem.before, fillLineOfText);

helpers.each(bodyItem.lines, function(line) {
// Draw Legend-like boxes if needed
if (drawColorBoxes) {
// Fill a white rect so that colours merge nicely if the opacity is < 1
ctx.fillStyle = mergeOpacity(vm.legendColorBackground, opacity);
ctx.fillStyle = vm.legendColorBackground;
ctx.fillRect(pt.x, pt.y, bodyFontSize, bodyFontSize);

// Border
ctx.lineWidth = 1;
ctx.strokeStyle = mergeOpacity(vm.labelColors[i].borderColor, opacity);
ctx.strokeStyle = vm.labelColors[i].borderColor;
ctx.strokeRect(pt.x, pt.y, bodyFontSize, bodyFontSize);

// Inner square
ctx.fillStyle = mergeOpacity(vm.labelColors[i].backgroundColor, opacity);
ctx.fillStyle = vm.labelColors[i].backgroundColor;
ctx.fillRect(pt.x + 1, pt.y + 1, bodyFontSize - 2, bodyFontSize - 2);
ctx.fillStyle = textColor;
}
Expand All @@ -820,7 +812,7 @@ var exports = module.exports = Element.extend({
pt.y -= bodySpacing; // Remove last body spacing
},

drawFooter: function(pt, vm, ctx, opacity) {
drawFooter: function(pt, vm, ctx) {
var footer = vm.footer;

if (footer.length) {
Expand All @@ -829,7 +821,7 @@ var exports = module.exports = Element.extend({
ctx.textAlign = vm._footerAlign;
ctx.textBaseline = 'top';

ctx.fillStyle = mergeOpacity(vm.footerFontColor, opacity);
ctx.fillStyle = vm.footerFontColor;
ctx.font = helpers.fontString(vm.footerFontSize, vm._footerFontStyle, vm._footerFontFamily);

helpers.each(footer, function(line) {
Expand All @@ -839,9 +831,9 @@ var exports = module.exports = Element.extend({
}
},

drawBackground: function(pt, vm, ctx, tooltipSize, opacity) {
ctx.fillStyle = mergeOpacity(vm.backgroundColor, opacity);
ctx.strokeStyle = mergeOpacity(vm.borderColor, opacity);
drawBackground: function(pt, vm, ctx, tooltipSize) {
ctx.fillStyle = vm.backgroundColor;
ctx.strokeStyle = vm.borderColor;
ctx.lineWidth = vm.borderWidth;
var xAlign = vm.xAlign;
var yAlign = vm.yAlign;
Expand Down Expand Up @@ -906,21 +898,26 @@ var exports = module.exports = Element.extend({
var hasTooltipContent = vm.title.length || vm.beforeBody.length || vm.body.length || vm.afterBody.length || vm.footer.length;

if (this._options.enabled && hasTooltipContent) {
ctx.save();
ctx.globalAlpha = opacity;

// Draw Background
this.drawBackground(pt, vm, ctx, tooltipSize, opacity);
this.drawBackground(pt, vm, ctx, tooltipSize);

// Draw Title, Body, and Footer
pt.x += vm.xPadding;
pt.y += vm.yPadding;

// Titles
this.drawTitle(pt, vm, ctx, opacity);
this.drawTitle(pt, vm, ctx);

// Body
this.drawBody(pt, vm, ctx, opacity);
this.drawBody(pt, vm, ctx);

// Footer
this.drawFooter(pt, vm, ctx, opacity);
this.drawFooter(pt, vm, ctx);

ctx.restore();
}
},

Expand Down
105 changes: 105 additions & 0 deletions test/fixtures/core.tooltip/opacity.js
@@ -0,0 +1,105 @@
var pattern;
var gradient;

module.exports = {
config: {
type: 'line',
data: {
datasets: [{
data: [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8],
pointBorderColor: '#ff0000',
pointBackgroundColor: '#00ff00',
showLine: false
}, {
label: '',
data: [4, 4, 4, 4, 4, 5, 3, 4, 4, 4, 4],
showLine: false
}, {
label: '',
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
showLine: false
}],
labels: ['', '', '', '', '', '', '', '', '', '', '']
},
options: {
legend: false,
title: false,
scales: {
xAxes: [{display: false}],
yAxes: [{display: false}]
},
elements: {
line: {
fill: false
}
},
tooltips: {
mode: 'nearest',
intersect: false,
callbacks: {
label: function() {
return '\u200b';
}
}
},
layout: {
padding: 15
}
},
plugins: [{
beforeDatasetsUpdate: function(chart) {
if (!pattern) {
var patternCanvas = document.createElement('canvas');
var patternContext = patternCanvas.getContext('2d');
patternCanvas.width = 6;
patternCanvas.height = 6;
patternContext.fillStyle = '#ff0000';
patternContext.fillRect(0, 0, 6, 6);
patternContext.fillStyle = '#ffff00';
patternContext.fillRect(0, 0, 4, 4);
pattern = patternContext.createPattern(patternCanvas, 'repeat');
}
chart.config.data.datasets[1].pointBorderColor = pattern;
chart.config.data.datasets[1].pointBackgroundColor = pattern;

if (!gradient) {
gradient = chart.ctx.createLinearGradient(0, 0, 512, 256);
gradient.addColorStop(0, '#ff0000');
gradient.addColorStop(1, '#0000ff');
}
chart.config.data.datasets[2].pointBorderColor = gradient;
chart.config.data.datasets[2].pointBackgroundColor = gradient;

return true;
},
afterDraw: function(chart) {
var canvas = chart.canvas;
var rect = canvas.getBoundingClientRect();
var point, event;

for (var i = 0; i < 3; ++i) {
for (var j = 0; j < 11; ++j) {
point = chart.getDatasetMeta(i).data[j];
event = {
type: 'mousemove',
target: canvas,
clientX: rect.left + point._model.x,
clientY: rect.top + point._model.y
};
chart.handleEvent(event);
chart.tooltip.handleEvent(event);
chart.tooltip.transition(1);
chart.tooltip._view.opacity = j / 10;
chart.tooltip.draw();
}
}
}
}]
},
options: {
canvas: {
height: 256,
width: 512
}
}
};
Binary file added test/fixtures/core.tooltip/opacity.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions test/specs/core.tooltip.tests.js
@@ -1,5 +1,7 @@
// Test the rectangle element
describe('Core.Tooltip', function() {
describe('auto', jasmine.fixture.specs('core.tooltip'));

describe('config', function() {
it('should not include the dataset label in the body string if not defined', function() {
var data = {
Expand Down

0 comments on commit 93152df

Please sign in to comment.