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

0 commit comments

Comments
 (0)