Skip to content

Commit 85a2004

Browse files
authored
Merge pull request #3048 from plotly/hover-labels-on-white-bg
Fix hover label coloring on white bgcolor
2 parents 4b52e42 + 864f941 commit 85a2004

File tree

2 files changed

+88
-13
lines changed

2 files changed

+88
-13
lines changed

src/components/fx/hover.js

+18-9
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,7 @@ function createHoverText(hoverData, opts, gd) {
703703

704704
var commonBgColor = commonLabelOpts.bgcolor || Color.defaultLine;
705705
var commonStroke = commonLabelOpts.bordercolor || Color.contrast(commonBgColor);
706+
var contrastColor = Color.contrast(commonBgColor);
706707

707708
lpath.style({
708709
fill: commonBgColor,
@@ -713,7 +714,7 @@ function createHoverText(hoverData, opts, gd) {
713714
.call(Drawing.font,
714715
commonLabelOpts.font.family || fontFamily,
715716
commonLabelOpts.font.size || fontSize,
716-
commonLabelOpts.font.color || Color.background
717+
commonLabelOpts.font.color || contrastColor
717718
)
718719
.call(svgTextUtils.positionText, 0, 0)
719720
.call(svgTextUtils.convertToTspans, gd);
@@ -795,12 +796,20 @@ function createHoverText(hoverData, opts, gd) {
795796
var name = '';
796797
var text = '';
797798

798-
// combine possible non-opaque trace color with bgColor
799-
var baseColor = Color.opacity(d.color) ? d.color : Color.defaultLine;
800-
var traceColor = Color.combine(baseColor, bgColor);
801-
799+
// combine possible non-opaque trace color with bgColor
800+
var color0 = d.bgcolor || d.color;
801+
// color for 'nums' part of the label
802+
var numsColor = Color.combine(
803+
Color.opacity(color0) ? color0 : Color.defaultLine,
804+
bgColor
805+
);
806+
// color for 'name' part of the label
807+
var nameColor = Color.combine(
808+
Color.opacity(d.color) ? d.color : Color.defaultLine,
809+
bgColor
810+
);
802811
// find a contrasting color for border and text
803-
var contrastColor = d.borderColor || Color.contrast(traceColor);
812+
var contrastColor = d.borderColor || Color.contrast(numsColor);
804813

805814
// to get custom 'name' labels pass cleanPoint
806815
if(d.nameOverride !== undefined) d.name = d.nameOverride;
@@ -869,7 +878,7 @@ function createHoverText(hoverData, opts, gd) {
869878
tx2.call(Drawing.font,
870879
d.fontFamily || fontFamily,
871880
d.fontSize || fontSize,
872-
traceColor)
881+
nameColor)
873882
.text(name)
874883
.attr('data-notex', 1)
875884
.call(svgTextUtils.positionText, 0, 0)
@@ -883,7 +892,7 @@ function createHoverText(hoverData, opts, gd) {
883892

884893
g.select('path')
885894
.style({
886-
fill: traceColor,
895+
fill: numsColor,
887896
stroke: contrastColor
888897
});
889898
var tbb = tx.node().getBoundingClientRect();
@@ -1189,7 +1198,7 @@ function cleanPoint(d, hovermode) {
11891198
}
11901199

11911200
fill('hoverinfo', 'hi', 'hoverinfo');
1192-
fill('color', 'hbg', 'hoverlabel.bgcolor');
1201+
fill('bgcolor', 'hbg', 'hoverlabel.bgcolor');
11931202
fill('borderColor', 'hbc', 'hoverlabel.bordercolor');
11941203
fill('fontFamily', 'htf', 'hoverlabel.font.family');
11951204
fill('fontSize', 'hts', 'hoverlabel.font.size');

test/jasmine/tests/hover_label_test.js

+70-4
Original file line numberDiff line numberDiff line change
@@ -2062,7 +2062,7 @@ describe('Test hover label custom styling:', function() {
20622062
});
20632063
assertCommonLabel({
20642064
path: ['rgb(255, 255, 255)', 'rgb(68, 68, 68)'],
2065-
text: [13, 'Arial', 'rgb(255, 255, 255)']
2065+
text: [13, 'Arial', 'rgb(68, 68, 68)']
20662066
});
20672067
})
20682068
.then(function() {
@@ -2074,7 +2074,7 @@ describe('Test hover label custom styling:', function() {
20742074
});
20752075
assertCommonLabel({
20762076
path: ['rgb(255, 255, 255)', 'rgb(68, 68, 68)'],
2077-
text: [13, 'Arial', 'rgb(255, 255, 255)']
2077+
text: [13, 'Arial', 'rgb(68, 68, 68)']
20782078
});
20792079
})
20802080
.then(function() {
@@ -2086,7 +2086,7 @@ describe('Test hover label custom styling:', function() {
20862086
});
20872087
assertCommonLabel({
20882088
path: ['rgb(255, 255, 255)', 'rgb(68, 68, 68)'],
2089-
text: [13, 'Arial', 'rgb(255, 255, 255)']
2089+
text: [13, 'Arial', 'rgb(68, 68, 68)']
20902090
});
20912091

20922092
// test arrayOk case
@@ -2113,7 +2113,7 @@ describe('Test hover label custom styling:', function() {
21132113
assertPtLabel(null);
21142114
assertCommonLabel({
21152115
path: ['rgb(255, 255, 255)', 'rgb(68, 68, 68)'],
2116-
text: [13, 'Arial', 'rgb(255, 255, 255)']
2116+
text: [13, 'Arial', 'rgb(68, 68, 68)']
21172117
});
21182118

21192119
// test base case
@@ -2203,6 +2203,72 @@ describe('Test hover label custom styling:', function() {
22032203
.then(done);
22042204
});
22052205

2206+
it('should work for x/y cartesian traces (multi-trace case)', function(done) {
2207+
var gd = createGraphDiv();
2208+
2209+
function assertNameLabel(expectation) {
2210+
var g = d3.selectAll('g.hovertext > text.name');
2211+
2212+
if(expectation === null) {
2213+
expect(g.size()).toBe(0);
2214+
} else {
2215+
g.each(function(_, i) {
2216+
var textStyle = window.getComputedStyle(this);
2217+
expect(textStyle.fill).toBe(expectation.color[i]);
2218+
});
2219+
}
2220+
}
2221+
2222+
Plotly.plot(gd, [{
2223+
x: [1, 2, 3],
2224+
y: [1, 2, 1],
2225+
}, {
2226+
x: [1, 2, 3],
2227+
y: [4, 5, 4],
2228+
}], {
2229+
hovermode: 'x',
2230+
})
2231+
.then(function() {
2232+
_hover(gd, { xval: gd._fullData[0].x[0] });
2233+
assertNameLabel({
2234+
color: ['rgb(31, 119, 180)', 'rgb(255, 127, 14)']
2235+
});
2236+
return Plotly.restyle(gd, 'marker.color', ['red', 'blue']);
2237+
})
2238+
.then(function() {
2239+
_hover(gd, { xval: gd._fullData[0].x[0] });
2240+
assertNameLabel({
2241+
color: ['rgb(255, 0, 0)', 'rgb(0, 0, 255)']
2242+
});
2243+
return Plotly.relayout(gd, 'hoverlabel.bgcolor', 'white');
2244+
})
2245+
.then(function() {
2246+
_hover(gd, { xval: gd._fullData[0].x[0] });
2247+
// should not affect the name font color
2248+
assertNameLabel({
2249+
color: ['rgb(255, 0, 0)', 'rgb(0, 0, 255)']
2250+
});
2251+
return Plotly.restyle(gd, 'marker.color', ['rgba(255,0,0,0.1)', 'rgba(0,0,255,0.1)']);
2252+
})
2253+
.then(function() {
2254+
_hover(gd, { xval: gd._fullData[0].x[0] });
2255+
// should blend with plot_bgcolor
2256+
assertNameLabel({
2257+
color: ['rgb(255, 179, 179)', 'rgb(179, 179, 255)']
2258+
});
2259+
return Plotly.restyle(gd, 'marker.color', ['rgba(255,0,0,0)', 'rgba(0,0,255,0)']);
2260+
})
2261+
.then(function() {
2262+
_hover(gd, { xval: gd._fullData[0].x[0] });
2263+
// uses default line color when opacity=0
2264+
assertNameLabel({
2265+
color: ['rgb(68, 68, 68)', 'rgb(68, 68, 68)']
2266+
});
2267+
})
2268+
.catch(failTest)
2269+
.then(done);
2270+
});
2271+
22062272
it('should work for 2d z cartesian traces', function(done) {
22072273
var gd = createGraphDiv();
22082274

0 commit comments

Comments
 (0)