Skip to content

Commit e301f5b

Browse files
committed
auto size heatmap text
1 parent 51de82b commit e301f5b

19 files changed

+79
-13
lines changed

src/plots/font_attributes.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ module.exports = function(opts) {
5353
description: '' + (opts.description || '') + ''
5454
};
5555

56+
if(opts.autoSize) attrs.size.dflt = 'auto';
57+
if(opts.autoColor) attrs.color.dflt = 'auto';
58+
5659
if(opts.arrayOk) {
5760
attrs.family.arrayOk = true;
5861
attrs.size.arrayOk = true;

src/traces/heatmap/attributes.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ module.exports = extendFlat({
126126
}),
127127
textfont: fontAttrs({
128128
editType: 'plot',
129+
autoSize: true,
130+
autoColor: true,
129131
colorEditType: 'style',
130132
description: 'Sets the text font.'
131133
}),

src/traces/heatmap/label_defaults.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ var Lib = require('../../lib');
55
module.exports = function handleHeatmapLabelDefaults(coerce, layout) {
66
coerce('texttemplate');
77

8-
var fontDflt = Lib.extendFlat({}, layout.font);
9-
fontDflt.color = undefined; // color contrast by default
8+
var fontDflt = Lib.extendFlat({}, layout.font, {
9+
color: 'auto',
10+
size: 'auto'
11+
});
1012
Lib.coerceFont(coerce, 'textfont', fontDflt);
1113
};

src/traces/heatmap/plot.js

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) {
3434
var plotGroup = d3.select(this);
3535
var cd0 = cd[0];
3636
var trace = cd0.trace;
37+
var xGap = trace.xgap || 0;
38+
var yGap = trace.ygap || 0;
3739

3840
var z = cd0.z;
3941
var x = cd0.x;
@@ -49,7 +51,7 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) {
4951
var xrev = false;
5052
var yrev = false;
5153

52-
var left, right, temp, top, bottom, i, j;
54+
var left, right, temp, top, bottom, i, j, k;
5355

5456
// TODO: if there are multiple overlapping categorical heatmaps,
5557
// or if we allow category sorting, then the categories may not be
@@ -298,8 +300,6 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) {
298300
} else { // zsmooth = false -> filling potentially large bricks works fastest with fillRect
299301
// gaps do not need to be exact integers, but if they *are* we will get
300302
// cleaner edges by rounding at least one edge
301-
var xGap = trace.xgap;
302-
var yGap = trace.ygap;
303303
var xGapLeft = Math.floor(xGap / 2);
304304
var yGapTop = Math.floor(yGap / 2);
305305

@@ -432,8 +432,17 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) {
432432
var _t = Lib.texttemplateString(texttemplate, obj, gd._fullLayout._d3locale, obj, trace._meta || {});
433433
if(!_t) continue;
434434

435+
var lines = _t.split('<br>');
436+
var nL = lines.length;
437+
var nC = 0;
438+
for(k = 0; k < nL; k++) {
439+
nC = Math.max(nC, lines[k].length);
440+
}
441+
435442
textData.push({
436-
t: _t,
443+
l: nL, // number of lines
444+
c: nC, // maximum number of chars in a line
445+
t: _t, // text
437446
x: _x,
438447
y: _y,
439448
z: zVal
@@ -444,10 +453,54 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) {
444453
var font = trace.textfont;
445454
var fontFamily = font.family;
446455
var fontSize = font.size;
456+
457+
if(!fontSize || fontSize === 'auto') {
458+
var minW = Infinity;
459+
var minH = Infinity;
460+
var maxL = 0;
461+
var maxC = 0;
462+
463+
for(k = 0; k < textData.length; k++) {
464+
var d = textData[k];
465+
maxL = Math.max(maxL, d.l);
466+
maxC = Math.max(maxC, d.c);
467+
468+
if(k < textData.length - 1) {
469+
var nextD = textData[k + 1];
470+
var dx = Math.abs(nextD.x - d.x);
471+
var dy = Math.abs(nextD.y - d.y);
472+
473+
if(dx) minW = Math.min(minW, dx);
474+
if(dy) minH = Math.min(minH, dy);
475+
}
476+
}
477+
478+
if(
479+
!isFinite(minW) ||
480+
!isFinite(minH)
481+
) {
482+
fontSize = 12;
483+
} else {
484+
minW -= xGap;
485+
minH -= yGap;
486+
487+
minW /= maxC;
488+
minH /= maxL;
489+
490+
minW /= LINE_SPACING / 2;
491+
minH /= LINE_SPACING;
492+
493+
fontSize = Math.min(
494+
Math.floor(minW),
495+
Math.floor(minH)
496+
);
497+
}
498+
}
499+
if(fontSize <= 0 || !isFinite(fontSize)) return;
500+
447501
var xFn = function(d) { return d.x; };
448502
var yFn = function(d) {
449-
var nlines = d.t.split('<br>').length;
450-
return d.y - fontSize * ((nlines * LINE_SPACING) / 2 - 1);
503+
return d.y - fontSize * ((d.l * LINE_SPACING) / 2 - 1);
451504
};
452505

453506
var labels = selectLabels(plotGroup).data(textData);
@@ -462,7 +515,7 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) {
462515
var thisLabel = d3.select(this);
463516

464517
var fontColor = font.color;
465-
if(!fontColor) {
518+
if(!fontColor || fontColor === 'auto') {
466519
fontColor = Color.contrast(
467520
'rgba(' +
468521
sclFunc(d.z).join() +

test/image/baselines/4.png

-9.24 KB
Loading
Loading
10.1 KB
Loading
-3.41 KB
Loading
Loading
2.06 KB
Loading
Loading
1.71 KB
Loading
22.4 KB
Loading
13.5 KB
Loading

test/image/mocks/4.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"data": [
33
{
44
"texttemplate": "%{z}",
5+
"textfont": { "family": "Times New Roman" },
56
"z": [
67
[
78
1,

test/image/mocks/heatmap_brick_padding.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"data": [
33
{
4+
"texttemplate": "%{z}",
45
"z": [
56
[1, 2, 3, 4, 5],
67
[3, 4, 5, 6, 7],

test/image/mocks/heatmap_categoryorder.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@
1414
"data": [{
1515
"type": "heatmap",
1616
"texttemplate": "x: %{x}<br>y: %{y}<br>z: %{z}",
17-
"textfont": {
18-
"size": 14
19-
},
2017

2118
"x": ["z", "y", "x", "w"],
2219
"y": ["d", "c", "b", "a"],

test/image/mocks/heatmap_columnar.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
"text": ["zero", "fifty", "one hundred", "fifty", "zero", "two hundred<br>and fifty-five", "one hundred", "five hundred<br>and ten", "one thousand ten"],
88
"texttemplate": "%{text}",
99
"textfont": {
10-
"size": 20,
1110
"color": "rgba(255,255,255,0.5)"
1211
}
1312
}],

test/plot-schema.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21560,6 +21560,7 @@
2156021560
},
2156121561
"textfont": {
2156221562
"color": {
21563+
"dflt": "auto",
2156321564
"editType": "style",
2156421565
"valType": "color"
2156521566
},
@@ -21574,6 +21575,7 @@
2157421575
},
2157521576
"role": "object",
2157621577
"size": {
21578+
"dflt": "auto",
2157721579
"editType": "plot",
2157821580
"min": 1,
2157921581
"valType": "number"
@@ -26659,6 +26661,7 @@
2665926661
},
2666026662
"textfont": {
2666126663
"color": {
26664+
"dflt": "auto",
2666226665
"editType": "style",
2666326666
"valType": "color"
2666426667
},
@@ -26673,6 +26676,7 @@
2667326676
},
2667426677
"role": "object",
2667526678
"size": {
26679+
"dflt": "auto",
2667626680
"editType": "plot",
2667726681
"min": 1,
2667826682
"valType": "number"
@@ -30379,6 +30383,7 @@
3037930383
},
3038030384
"textfont": {
3038130385
"color": {
30386+
"dflt": "auto",
3038230387
"editType": "style",
3038330388
"valType": "color"
3038430389
},
@@ -30393,6 +30398,7 @@
3039330398
},
3039430399
"role": "object",
3039530400
"size": {
30401+
"dflt": "auto",
3039630402
"editType": "plot",
3039730403
"min": 1,
3039830404
"valType": "number"
@@ -31666,6 +31672,7 @@
3166631672
},
3166731673
"textfont": {
3166831674
"color": {
31675+
"dflt": "auto",
3166931676
"editType": "style",
3167031677
"valType": "color"
3167131678
},
@@ -31680,6 +31687,7 @@
3168031687
},
3168131688
"role": "object",
3168231689
"size": {
31690+
"dflt": "auto",
3168331691
"editType": "plot",
3168431692
"min": 1,
3168531693
"valType": "number"

0 commit comments

Comments
 (0)