diff --git a/draftlogs/6028_add.md b/draftlogs/6028_add.md new file mode 100644 index 00000000000..5d0683354d0 --- /dev/null +++ b/draftlogs/6028_add.md @@ -0,0 +1,2 @@ + - Add `texttemplate` and `textfont` to `heatmap` and `histogram2d` traces as well as + `histogram2dcontour` and `contour` traces when `coloring` is set "heatmap" [[#6028](https://github.com/plotly/plotly.js/pull/6028)] diff --git a/src/plots/font_attributes.js b/src/plots/font_attributes.js index 68ea0b1a11f..42c19c71a02 100644 --- a/src/plots/font_attributes.js +++ b/src/plots/font_attributes.js @@ -53,6 +53,9 @@ module.exports = function(opts) { description: '' + (opts.description || '') + '' }; + if(opts.autoSize) attrs.size.dflt = 'auto'; + if(opts.autoColor) attrs.color.dflt = 'auto'; + if(opts.arrayOk) { attrs.family.arrayOk = true; attrs.size.arrayOk = true; diff --git a/src/traces/contour/attributes.js b/src/traces/contour/attributes.js index ca6e8e3b2f5..d5f28aa1388 100644 --- a/src/traces/contour/attributes.js +++ b/src/traces/contour/attributes.js @@ -42,6 +42,18 @@ module.exports = extendFlat({ yhoverformat: axisHoverFormat('y'), zhoverformat: axisHoverFormat('z', 1), hovertemplate: heatmapAttrs.hovertemplate, + texttemplate: extendFlat({}, heatmapAttrs.texttemplate, { + description: [ + 'For this trace it only has an effect if `coloring` is set to *heatmap*.', + heatmapAttrs.texttemplate.description + ].join(' ') + }), + textfont: extendFlat({}, heatmapAttrs.textfont, { + description: [ + 'For this trace it only has an effect if `coloring` is set to *heatmap*.', + heatmapAttrs.textfont.description + ].join(' ') + }), hoverongaps: heatmapAttrs.hoverongaps, connectgaps: extendFlat({}, heatmapAttrs.connectgaps, { description: [ diff --git a/src/traces/contour/defaults.js b/src/traces/contour/defaults.js index d0ce4a55428..c1ebd9be8e9 100644 --- a/src/traces/contour/defaults.js +++ b/src/traces/contour/defaults.js @@ -7,6 +7,7 @@ var handlePeriodDefaults = require('../scatter/period_defaults'); var handleConstraintDefaults = require('./constraint_defaults'); var handleContoursDefaults = require('./contours_defaults'); var handleStyleDefaults = require('./style_defaults'); +var handleHeatmapLabelDefaults = require('../heatmap/label_defaults'); var attributes = require('./attributes'); @@ -31,8 +32,8 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout coerce('text'); coerce('hovertext'); - coerce('hovertemplate'); coerce('hoverongaps'); + coerce('hovertemplate'); var isConstraint = (coerce('contours.type') === 'constraint'); coerce('connectgaps', Lib.isArray1D(traceOut.z)); @@ -43,4 +44,11 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout handleContoursDefaults(traceIn, traceOut, coerce, coerce2); handleStyleDefaults(traceIn, traceOut, coerce, layout); } + + if( + traceOut.contours && + traceOut.contours.coloring === 'heatmap' + ) { + handleHeatmapLabelDefaults(coerce, layout); + } }; diff --git a/src/traces/heatmap/attributes.js b/src/traces/heatmap/attributes.js index db0bfd6bf10..d2faa7d1649 100644 --- a/src/traces/heatmap/attributes.js +++ b/src/traces/heatmap/attributes.js @@ -2,8 +2,10 @@ var scatterAttrs = require('../scatter/attributes'); var baseAttrs = require('../../plots/attributes'); +var fontAttrs = require('../../plots/font_attributes'); var axisHoverFormat = require('../../plots/cartesian/axis_format_attributes').axisHoverFormat; var hovertemplateAttrs = require('../../plots/template_attributes').hovertemplateAttrs; +var texttemplateAttrs = require('../../plots/template_attributes').texttemplateAttrs; var colorScaleAttrs = require('../../components/colorscale/attributes'); var extendFlat = require('../../lib/extend').extendFlat; @@ -116,6 +118,20 @@ module.exports = extendFlat({ zhoverformat: axisHoverFormat('z', 1), hovertemplate: hovertemplateAttrs(), + texttemplate: texttemplateAttrs({ + arrayOk: false, + editType: 'plot' + }, { + keys: ['x', 'y', 'z', 'text'] + }), + textfont: fontAttrs({ + editType: 'plot', + autoSize: true, + autoColor: true, + colorEditType: 'style', + description: 'Sets the text font.' + }), + showlegend: extendFlat({}, baseAttrs.showlegend, {dflt: false}) }, { transforms: undefined diff --git a/src/traces/heatmap/defaults.js b/src/traces/heatmap/defaults.js index a9fb34d3aa7..5e5acc5111a 100644 --- a/src/traces/heatmap/defaults.js +++ b/src/traces/heatmap/defaults.js @@ -3,6 +3,7 @@ var Lib = require('../../lib'); var handleXYZDefaults = require('./xyz_defaults'); +var handleHeatmapLabelDefaults = require('./label_defaults'); var handlePeriodDefaults = require('../scatter/period_defaults'); var handleStyleDefaults = require('./style_defaults'); var colorscaleDefaults = require('../../components/colorscale/defaults'); @@ -28,6 +29,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout coerce('hovertext'); coerce('hovertemplate'); + handleHeatmapLabelDefaults(coerce, layout); handleStyleDefaults(traceIn, traceOut, coerce, layout); coerce('hoverongaps'); diff --git a/src/traces/heatmap/label_defaults.js b/src/traces/heatmap/label_defaults.js new file mode 100644 index 00000000000..4ed899111b4 --- /dev/null +++ b/src/traces/heatmap/label_defaults.js @@ -0,0 +1,13 @@ +'use strict'; + +var Lib = require('../../lib'); + +module.exports = function handleHeatmapLabelDefaults(coerce, layout) { + coerce('texttemplate'); + + var fontDflt = Lib.extendFlat({}, layout.font, { + color: 'auto', + size: 'auto' + }); + Lib.coerceFont(coerce, 'textfont', fontDflt); +}; diff --git a/src/traces/heatmap/plot.js b/src/traces/heatmap/plot.js index e511866bb07..1db9318bd4c 100644 --- a/src/traces/heatmap/plot.js +++ b/src/traces/heatmap/plot.js @@ -4,9 +4,27 @@ var d3 = require('@plotly/d3'); var tinycolor = require('tinycolor2'); var Registry = require('../../registry'); +var Drawing = require('../../components/drawing'); +var Axes = require('../../plots/cartesian/axes'); var Lib = require('../../lib'); +var svgTextUtils = require('../../lib/svg_text_utils'); +var formatLabels = require('../scatter/format_labels'); +var Color = require('../../components/color'); +var extractOpts = require('../../components/colorscale').extractOpts; var makeColorScaleFuncFromTrace = require('../../components/colorscale').makeColorScaleFuncFromTrace; var xmlnsNamespaces = require('../../constants/xmlns_namespaces'); +var alignmentConstants = require('../../constants/alignment'); +var LINE_SPACING = alignmentConstants.LINE_SPACING; + +var labelClass = 'heatmap-label'; + +function selectLabels(plotGroup) { + return plotGroup.selectAll('g.' + labelClass); +} + +function removeLabels(plotGroup) { + selectLabels(plotGroup).remove(); +} module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) { var xa = plotinfo.xaxis; @@ -16,6 +34,8 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) { var plotGroup = d3.select(this); var cd0 = cd[0]; var trace = cd0.trace; + var xGap = trace.xgap || 0; + var yGap = trace.ygap || 0; var z = cd0.z; var x = cd0.x; @@ -31,7 +51,7 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) { var xrev = false; var yrev = false; - var left, right, temp, top, bottom, i; + var left, right, temp, top, bottom, i, j, k; // TODO: if there are multiple overlapping categorical heatmaps, // or if we allow category sorting, then the categories may not be @@ -112,6 +132,8 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) { if(isOffScreen) { var noImage = plotGroup.selectAll('image').data([]); noImage.exit().remove(); + + removeLabels(plotGroup); return; } @@ -167,7 +189,7 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) { var gcount = 0; var bcount = 0; - var xb, j, xi, v, row, c; + var xb, xi, v, row, c; function setColor(v, pixsize) { if(v !== undefined) { @@ -278,8 +300,6 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) { } else { // zsmooth = false -> filling potentially large bricks works fastest with fillRect // gaps do not need to be exact integers, but if they *are* we will get // cleaner edges by rounding at least one edge - var xGap = trace.xgap; - var yGap = trace.ygap; var xGapLeft = Math.floor(xGap / 2); var yGapTop = Math.floor(yGap / 2); @@ -332,6 +352,185 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) { y: top, 'xlink:href': canvas.toDataURL('image/png') }); + + removeLabels(plotGroup); + + var texttemplate = trace.texttemplate; + if(texttemplate) { + // dummy axis for formatting the z value + var cOpts = extractOpts(trace); + var dummyAx = { + type: 'linear', + range: [cOpts.min, cOpts.max], + _separators: xa._separators, + _numFormat: xa._numFormat + }; + + var aHistogram2dContour = trace.type === 'histogram2dcontour'; + var aContour = trace.type === 'contour'; + var iStart = aContour ? 1 : 0; + var iStop = aContour ? m - 1 : m; + var jStart = aContour ? 1 : 0; + var jStop = aContour ? n - 1 : n; + + var textData = []; + for(i = iStart; i < iStop; i++) { + var yVal; + if(aContour) { + yVal = cd0.y[i]; + } else if(aHistogram2dContour) { + if(i === 0 || i === m - 1) continue; + yVal = cd0.y[i]; + } else if(cd0.yCenter) { + yVal = cd0.yCenter[i]; + } else { + if(i + 1 === m && cd0.y[i + 1] === undefined) continue; + yVal = (cd0.y[i] + cd0.y[i + 1]) / 2; + } + + var _y = Math.round(ya.c2p(yVal)); + if(0 > _y || _y > ya._length) continue; + + for(j = jStart; j < jStop; j++) { + var xVal; + if(aContour) { + xVal = cd0.x[j]; + } else if(aHistogram2dContour) { + if(j === 0 || j === n - 1) continue; + xVal = cd0.x[j]; + } else if(cd0.xCenter) { + xVal = cd0.xCenter[j]; + } else { + if(j + 1 === n && cd0.x[j + 1] === undefined) continue; + xVal = (cd0.x[j] + cd0.x[j + 1]) / 2; + } + + var _x = Math.round(xa.c2p(xVal)); + if(0 > _x || _x > xa._length) continue; + + var obj = formatLabels({ + x: xVal, + y: yVal + }, trace, gd._fullLayout); + + obj.x = xVal; + obj.y = yVal; + + var zVal = cd0.z[i][j]; + if(zVal === undefined) { + obj.z = ''; + obj.zLabel = ''; + } else { + obj.z = zVal; + obj.zLabel = Axes.tickText(dummyAx, zVal, 'hover').text; + } + + var theText = cd0.text && cd0.text[i] && cd0.text[i][j]; + if(theText === undefined || theText === false) theText = ''; + obj.text = theText; + + var _t = Lib.texttemplateString(texttemplate, obj, gd._fullLayout._d3locale, obj, trace._meta || {}); + if(!_t) continue; + + var lines = _t.split('
'); + var nL = lines.length; + var nC = 0; + for(k = 0; k < nL; k++) { + nC = Math.max(nC, lines[k].length); + } + + textData.push({ + l: nL, // number of lines + c: nC, // maximum number of chars in a line + t: _t, // text + x: _x, + y: _y, + z: zVal + }); + } + } + + var font = trace.textfont; + var fontFamily = font.family; + var fontSize = font.size; + + if(!fontSize || fontSize === 'auto') { + var minW = Infinity; + var minH = Infinity; + var maxL = 0; + var maxC = 0; + + for(k = 0; k < textData.length; k++) { + var d = textData[k]; + maxL = Math.max(maxL, d.l); + maxC = Math.max(maxC, d.c); + + if(k < textData.length - 1) { + var nextD = textData[k + 1]; + var dx = Math.abs(nextD.x - d.x); + var dy = Math.abs(nextD.y - d.y); + + if(dx) minW = Math.min(minW, dx); + if(dy) minH = Math.min(minH, dy); + } + } + + if( + !isFinite(minW) || + !isFinite(minH) + ) { + fontSize = 12; + } else { + minW -= xGap; + minH -= yGap; + + minW /= maxC; + minH /= maxL; + + minW /= LINE_SPACING / 2; + minH /= LINE_SPACING; + + fontSize = Math.min( + Math.floor(minW), + Math.floor(minH) + ); + } + } + if(fontSize <= 0 || !isFinite(fontSize)) return; + + var xFn = function(d) { return d.x; }; + var yFn = function(d) { + return d.y - fontSize * ((d.l * LINE_SPACING) / 2 - 1); + }; + + var labels = selectLabels(plotGroup).data(textData); + + labels + .enter() + .append('g') + .classed(labelClass, 1) + .append('text') + .attr('text-anchor', 'middle') + .each(function(d) { + var thisLabel = d3.select(this); + + var fontColor = font.color; + if(!fontColor || fontColor === 'auto') { + fontColor = Color.contrast( + 'rgba(' + + sclFunc(d.z).join() + + ')' + ); + } + + thisLabel + .attr('data-notex', 1) + .call(svgTextUtils.positionText, xFn(d), yFn(d)) + .call(Drawing.font, fontFamily, fontSize, fontColor) + .text(d.t) + .call(svgTextUtils.convertToTspans, gd); + }); + } }); }; diff --git a/src/traces/histogram2d/attributes.js b/src/traces/histogram2d/attributes.js index 79c84651228..629a8eca23c 100644 --- a/src/traces/histogram2d/attributes.js +++ b/src/traces/histogram2d/attributes.js @@ -6,6 +6,7 @@ var heatmapAttrs = require('../heatmap/attributes'); var baseAttrs = require('../../plots/attributes'); var axisHoverFormat = require('../../plots/cartesian/axis_format_attributes').axisHoverFormat; var hovertemplateAttrs = require('../../plots/template_attributes').hovertemplateAttrs; +var texttemplateAttrs = require('../../plots/template_attributes').texttemplateAttrs; var colorScaleAttrs = require('../../components/colorscale/attributes'); var extendFlat = require('../../lib/extend').extendFlat; @@ -69,6 +70,13 @@ module.exports = extendFlat( yhoverformat: axisHoverFormat('y'), zhoverformat: axisHoverFormat('z', 1), hovertemplate: hovertemplateAttrs({}, {keys: 'z'}), + texttemplate: texttemplateAttrs({ + arrayOk: false, + editType: 'plot' + }, { + keys: 'z' + }), + textfont: heatmapAttrs.textfont, showlegend: extendFlat({}, baseAttrs.showlegend, {dflt: false}) }, colorScaleAttrs('', {cLetter: 'z', autoColorDflt: false}) diff --git a/src/traces/histogram2d/defaults.js b/src/traces/histogram2d/defaults.js index 4b942bbea0c..9a794ef329b 100644 --- a/src/traces/histogram2d/defaults.js +++ b/src/traces/histogram2d/defaults.js @@ -5,6 +5,7 @@ var Lib = require('../../lib'); var handleSampleDefaults = require('./sample_defaults'); var handleStyleDefaults = require('../heatmap/style_defaults'); var colorscaleDefaults = require('../../components/colorscale/defaults'); +var handleHeatmapLabelDefaults = require('../heatmap/label_defaults'); var attributes = require('./attributes'); @@ -19,6 +20,9 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout handleStyleDefaults(traceIn, traceOut, coerce, layout); colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'}); coerce('hovertemplate'); + + handleHeatmapLabelDefaults(coerce, layout); + coerce('xhoverformat'); coerce('yhoverformat'); }; diff --git a/src/traces/histogram2dcontour/attributes.js b/src/traces/histogram2dcontour/attributes.js index 8423b9ab57f..f1feef7e561 100644 --- a/src/traces/histogram2dcontour/attributes.js +++ b/src/traces/histogram2dcontour/attributes.js @@ -42,7 +42,9 @@ module.exports = extendFlat({ xhoverformat: axisHoverFormat('x'), yhoverformat: axisHoverFormat('y'), zhoverformat: axisHoverFormat('z', 1), - hovertemplate: histogram2dAttrs.hovertemplate + hovertemplate: histogram2dAttrs.hovertemplate, + texttemplate: contourAttrs.texttemplate, + textfont: contourAttrs.textfont }, colorScaleAttrs('', { cLetter: 'z', diff --git a/src/traces/histogram2dcontour/defaults.js b/src/traces/histogram2dcontour/defaults.js index f60f2aadf70..8f78147079f 100644 --- a/src/traces/histogram2dcontour/defaults.js +++ b/src/traces/histogram2dcontour/defaults.js @@ -5,6 +5,7 @@ var Lib = require('../../lib'); var handleSampleDefaults = require('../histogram2d/sample_defaults'); var handleContoursDefaults = require('../contour/contours_defaults'); var handleStyleDefaults = require('../contour/style_defaults'); +var handleHeatmapLabelDefaults = require('../heatmap/label_defaults'); var attributes = require('./attributes'); @@ -22,7 +23,13 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout handleContoursDefaults(traceIn, traceOut, coerce, coerce2); handleStyleDefaults(traceIn, traceOut, coerce, layout); - coerce('hovertemplate'); coerce('xhoverformat'); coerce('yhoverformat'); + coerce('hovertemplate'); + if( + traceOut.contours && + traceOut.contours.coloring === 'heatmap' + ) { + handleHeatmapLabelDefaults(coerce, layout); + } }; diff --git a/test/image/baselines/13.png b/test/image/baselines/13.png index a5489ae7ed5..69eefd31f1e 100644 Binary files a/test/image/baselines/13.png and b/test/image/baselines/13.png differ diff --git a/test/image/baselines/4.png b/test/image/baselines/4.png index 66e17fc7106..c9ab612a66f 100644 Binary files a/test/image/baselines/4.png and b/test/image/baselines/4.png differ diff --git a/test/image/baselines/contour_heatmap_coloring_reversescale.png b/test/image/baselines/contour_heatmap_coloring_reversescale.png index 7ac1ae07d8c..97cc01d6d91 100644 Binary files a/test/image/baselines/contour_heatmap_coloring_reversescale.png and b/test/image/baselines/contour_heatmap_coloring_reversescale.png differ diff --git a/test/image/baselines/contour_legend-colorscale.png b/test/image/baselines/contour_legend-colorscale.png index c5d327e7c8d..6aea01c694d 100644 Binary files a/test/image/baselines/contour_legend-colorscale.png and b/test/image/baselines/contour_legend-colorscale.png differ diff --git a/test/image/baselines/heatmap_brick_padding.png b/test/image/baselines/heatmap_brick_padding.png index 7f40efbd1c5..b8620ac7c74 100644 Binary files a/test/image/baselines/heatmap_brick_padding.png and b/test/image/baselines/heatmap_brick_padding.png differ diff --git a/test/image/baselines/heatmap_categoryorder.png b/test/image/baselines/heatmap_categoryorder.png index 5bf124f2881..a76a54c1641 100644 Binary files a/test/image/baselines/heatmap_categoryorder.png and b/test/image/baselines/heatmap_categoryorder.png differ diff --git a/test/image/baselines/heatmap_columnar.png b/test/image/baselines/heatmap_columnar.png index 2c4173ca01c..04d545dea86 100644 Binary files a/test/image/baselines/heatmap_columnar.png and b/test/image/baselines/heatmap_columnar.png differ diff --git a/test/image/baselines/heatmap_xyz-gaps-on-sides.png b/test/image/baselines/heatmap_xyz-gaps-on-sides.png index 755bc297038..66aae47f18d 100644 Binary files a/test/image/baselines/heatmap_xyz-gaps-on-sides.png and b/test/image/baselines/heatmap_xyz-gaps-on-sides.png differ diff --git a/test/image/baselines/hist2d_summed.png b/test/image/baselines/hist2d_summed.png index 4b089c86a14..49680d69708 100644 Binary files a/test/image/baselines/hist2d_summed.png and b/test/image/baselines/hist2d_summed.png differ diff --git a/test/image/baselines/histogram2d_bingroup-coloraxis.png b/test/image/baselines/histogram2d_bingroup-coloraxis.png index f2ceb71c5e1..f88342bc1ce 100644 Binary files a/test/image/baselines/histogram2d_bingroup-coloraxis.png and b/test/image/baselines/histogram2d_bingroup-coloraxis.png differ diff --git a/test/image/baselines/histogram2d_bingroup.png b/test/image/baselines/histogram2d_bingroup.png index 31a28020673..9fc00b968e4 100644 Binary files a/test/image/baselines/histogram2d_bingroup.png and b/test/image/baselines/histogram2d_bingroup.png differ diff --git a/test/image/baselines/histogram2d_legend.png b/test/image/baselines/histogram2d_legend.png index 1c9d618b07b..242d4d68d16 100644 Binary files a/test/image/baselines/histogram2d_legend.png and b/test/image/baselines/histogram2d_legend.png differ diff --git a/test/image/baselines/zsmooth_methods.png b/test/image/baselines/zsmooth_methods.png index be3d3ce3135..cf25b9e281e 100644 Binary files a/test/image/baselines/zsmooth_methods.png and b/test/image/baselines/zsmooth_methods.png differ diff --git a/test/image/mocks/13.json b/test/image/mocks/13.json index b324b028eb3..e960788566c 100644 --- a/test/image/mocks/13.json +++ b/test/image/mocks/13.json @@ -1,6 +1,8 @@ { "data": [ { + "texttemplate": "%{z:.1f}", + "textfont": {"size": 8}, "z": [ [ 1, diff --git a/test/image/mocks/4.json b/test/image/mocks/4.json index 82a752d3d7b..4b525d12ffa 100644 --- a/test/image/mocks/4.json +++ b/test/image/mocks/4.json @@ -1,6 +1,8 @@ { "data": [ { + "texttemplate": "%{z}", + "textfont": { "family": "Times New Roman" }, "z": [ [ 1, diff --git a/test/image/mocks/contour_heatmap_coloring_reversescale.json b/test/image/mocks/contour_heatmap_coloring_reversescale.json index 1237412277b..0e754f9f3a3 100644 --- a/test/image/mocks/contour_heatmap_coloring_reversescale.json +++ b/test/image/mocks/contour_heatmap_coloring_reversescale.json @@ -11,6 +11,7 @@ "x": [ -9, -6, -5, -3, -1 ], "y": [ 0, 1, 4, 5, 7 ], "type": "contour", + "texttemplate": "%{z}", "contours": { "coloring": "heatmap" }, @@ -33,6 +34,7 @@ "x": [ -9, -6, -5, -3, -1 ], "y": [ 0, 1, 4, 5, 7 ], "type": "contour", + "texttemplate": "%{z}", "contours": { "coloring": "heatmap" }, diff --git a/test/image/mocks/contour_legend-colorscale.json b/test/image/mocks/contour_legend-colorscale.json index 90858a3504b..19260610902 100644 --- a/test/image/mocks/contour_legend-colorscale.json +++ b/test/image/mocks/contour_legend-colorscale.json @@ -58,6 +58,13 @@ } ], "layout": { + "template": { + "data": { + "contour": [{ + "texttemplate": "%{z:.2s}" + }] + } + }, "title": {"text": "contour legends with heatmap coloring
red-blue should be equal to reversed blue-red.
i.e. display identical legends for identical graphs"}, "margin": { "t": 125, diff --git a/test/image/mocks/heatmap_brick_padding.json b/test/image/mocks/heatmap_brick_padding.json index bfad761d6f1..2e88031e022 100644 --- a/test/image/mocks/heatmap_brick_padding.json +++ b/test/image/mocks/heatmap_brick_padding.json @@ -1,6 +1,7 @@ { "data": [ { + "texttemplate": "%{z}", "z": [ [1, 2, 3, 4, 5], [3, 4, 5, 6, 7], diff --git a/test/image/mocks/heatmap_categoryorder.json b/test/image/mocks/heatmap_categoryorder.json index be1c521e398..0feee9149ab 100644 --- a/test/image/mocks/heatmap_categoryorder.json +++ b/test/image/mocks/heatmap_categoryorder.json @@ -13,6 +13,7 @@ }, "data": [{ "type": "heatmap", + "texttemplate": "x: %{x}
y: %{y}
z: %{z}", "x": ["z", "y", "x", "w"], "y": ["d", "c", "b", "a"], diff --git a/test/image/mocks/heatmap_columnar.json b/test/image/mocks/heatmap_columnar.json index 8c75c673a0e..3745f993b27 100644 --- a/test/image/mocks/heatmap_columnar.json +++ b/test/image/mocks/heatmap_columnar.json @@ -3,7 +3,12 @@ "type": "heatmap", "x": ["a", "a", "a", "b", "b", "b", "c", "c", "c"], "y": ["A", "B", "C", "A", "B", "C", "A", "B", "C"], - "z": [0, 50, 100, 50, 0, 255, 100, 510, 1010] + "z": [0, 50, 100, 50, 0, 255, 100, 510, 1010], + "text": ["zero", "fifty", "one hundred", "fifty", "zero", "two hundred
and fifty-five", "one hundred", "five hundred
and ten", "one thousand ten"], + "texttemplate": "%{text}", + "textfont": { + "color": "rgba(255,255,255,0.5)" + } }], "layout": { "xaxis": { diff --git a/test/image/mocks/heatmap_xyz-gaps-on-sides.json b/test/image/mocks/heatmap_xyz-gaps-on-sides.json index f799267b8cf..2e8ec1c04e3 100644 --- a/test/image/mocks/heatmap_xyz-gaps-on-sides.json +++ b/test/image/mocks/heatmap_xyz-gaps-on-sides.json @@ -1,6 +1,7 @@ { "data": [ { + "texttemplate": "%{z:.3f}", "x": [ 50076, -42372, diff --git a/test/image/mocks/hist2d_summed.json b/test/image/mocks/hist2d_summed.json index c149047606e..26870adef2b 100644 --- a/test/image/mocks/hist2d_summed.json +++ b/test/image/mocks/hist2d_summed.json @@ -25,6 +25,7 @@ "5", "6" ], + "texttemplate": "%{z} %{y}
%{x}", "type": "histogram2d", "histfunc": "sum" } diff --git a/test/image/mocks/histogram2d_bingroup-coloraxis.json b/test/image/mocks/histogram2d_bingroup-coloraxis.json index e1dc314b892..988082fd331 100644 --- a/test/image/mocks/histogram2d_bingroup-coloraxis.json +++ b/test/image/mocks/histogram2d_bingroup-coloraxis.json @@ -586,6 +586,13 @@ } ], "layout": { + "template": { + "data": { + "histogram2d": [{ + "texttemplate": "%{z}" + }] + } + }, "annotations": [ { "showarrow": false, diff --git a/test/image/mocks/histogram2d_bingroup.json b/test/image/mocks/histogram2d_bingroup.json index 7c1891eea1b..ab4fab78e74 100644 --- a/test/image/mocks/histogram2d_bingroup.json +++ b/test/image/mocks/histogram2d_bingroup.json @@ -69,6 +69,13 @@ } ], "layout": { + "template": { + "data": { + "histogram2d": [{ + "texttemplate": "%{z}" + }] + } + }, "grid": { "rows": 4, "columns": 2, diff --git a/test/image/mocks/histogram2d_legend.json b/test/image/mocks/histogram2d_legend.json index 41e1231adf9..8081a676d53 100644 --- a/test/image/mocks/histogram2d_legend.json +++ b/test/image/mocks/histogram2d_legend.json @@ -28,6 +28,7 @@ "histfunc": "sum", "showlegend": true, "showscale": false, + "texttemplate": "%{z}", "type": "histogram2d", "name": "histogram2d" }, @@ -62,6 +63,7 @@ "showlegend": true, "showscale": false, "reversescale": true, + "texttemplate": "%{z}", "type": "histogram2d", "name": "histogram2d reversed scale" }, @@ -95,6 +97,8 @@ "histfunc": "sum", "showlegend": true, "showscale": false, + "texttemplate": "%{z}", + "contours": {"coloring": "heatmap"}, "type": "histogram2dcontour", "name": "histogram2dcontour" }, @@ -129,6 +133,8 @@ "showlegend": true, "showscale": false, "reversescale": true, + "texttemplate": "%{z}", + "contours": {"coloring": "heatmap"}, "type": "histogram2dcontour", "name": "histogram2dcontour reversed scale" } diff --git a/test/image/mocks/zsmooth_methods.json b/test/image/mocks/zsmooth_methods.json index 16a2a71104a..372b05fc02a 100644 --- a/test/image/mocks/zsmooth_methods.json +++ b/test/image/mocks/zsmooth_methods.json @@ -1,6 +1,7 @@ { "data": [ { + "texttemplate": "%{z:.1f}", "z": [ [ 0.1189977, @@ -31,6 +32,7 @@ "yaxis": "y" }, { + "texttemplate": "%{z:.1f}", "z": [ [ 0.1189977, @@ -61,6 +63,7 @@ "yaxis": "y2" }, { + "texttemplate": "%{z:.1f}", "z": [ [ 0.1189977, diff --git a/test/plot-schema.json b/test/plot-schema.json index a49f77f14a5..52672c1938f 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -21558,11 +21558,40 @@ "editType": "calc", "valType": "data_array" }, + "textfont": { + "color": { + "dflt": "auto", + "editType": "style", + "valType": "color" + }, + "description": "For this trace it only has an effect if `coloring` is set to *heatmap*. Sets the text font.", + "editType": "plot", + "family": { + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The Chart Studio Cloud (at https://chart-studio.plotly.com or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "plot", + "noBlank": true, + "strict": true, + "valType": "string" + }, + "role": "object", + "size": { + "dflt": "auto", + "editType": "plot", + "min": 1, + "valType": "number" + } + }, "textsrc": { "description": "Sets the source reference on Chart Studio Cloud for `text`.", "editType": "none", "valType": "string" }, + "texttemplate": { + "description": "For this trace it only has an effect if `coloring` is set to *heatmap*. Template string used for rendering the information text that appear on points. Note that this will override `textinfo`. Variables are inserted using %{variable}, for example \"y: %{y}\". Numbers are formatted using d3-format's syntax %{variable:d3-format}, for example \"Price: %{y:$.2f}\". https://github.com/d3/d3-format/tree/v1.4.5#d3-format for details on the formatting syntax. Dates are formatted using d3-time-format's syntax %{variable|d3-time-format}, for example \"Day: %{2019-01-01|%A}\". https://github.com/d3/d3-time-format/tree/v2.2.3#locale_format for details on the date formatting syntax. Every attributes that can be specified per-point (the ones that are `arrayOk: true`) are available. variables `x`, `y`, `z` and `text`.", + "dflt": "", + "editType": "plot", + "valType": "string" + }, "transforms": { "items": { "transform": { @@ -26630,11 +26659,40 @@ "editType": "calc", "valType": "data_array" }, + "textfont": { + "color": { + "dflt": "auto", + "editType": "style", + "valType": "color" + }, + "description": "Sets the text font.", + "editType": "plot", + "family": { + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The Chart Studio Cloud (at https://chart-studio.plotly.com or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "plot", + "noBlank": true, + "strict": true, + "valType": "string" + }, + "role": "object", + "size": { + "dflt": "auto", + "editType": "plot", + "min": 1, + "valType": "number" + } + }, "textsrc": { "description": "Sets the source reference on Chart Studio Cloud for `text`.", "editType": "none", "valType": "string" }, + "texttemplate": { + "description": "Template string used for rendering the information text that appear on points. Note that this will override `textinfo`. Variables are inserted using %{variable}, for example \"y: %{y}\". Numbers are formatted using d3-format's syntax %{variable:d3-format}, for example \"Price: %{y:$.2f}\". https://github.com/d3/d3-format/tree/v1.4.5#d3-format for details on the formatting syntax. Dates are formatted using d3-time-format's syntax %{variable|d3-time-format}, for example \"Day: %{2019-01-01|%A}\". https://github.com/d3/d3-time-format/tree/v2.2.3#locale_format for details on the date formatting syntax. Every attributes that can be specified per-point (the ones that are `arrayOk: true`) are available. variables `x`, `y`, `z` and `text`.", + "dflt": "", + "editType": "plot", + "valType": "string" + }, "transforms": { "items": { "transform": { @@ -30323,6 +30381,35 @@ "valType": "string" } }, + "textfont": { + "color": { + "dflt": "auto", + "editType": "style", + "valType": "color" + }, + "description": "Sets the text font.", + "editType": "plot", + "family": { + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The Chart Studio Cloud (at https://chart-studio.plotly.com or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "plot", + "noBlank": true, + "strict": true, + "valType": "string" + }, + "role": "object", + "size": { + "dflt": "auto", + "editType": "plot", + "min": 1, + "valType": "number" + } + }, + "texttemplate": { + "description": "Template string used for rendering the information text that appear on points. Note that this will override `textinfo`. Variables are inserted using %{variable}, for example \"y: %{y}\". Numbers are formatted using d3-format's syntax %{variable:d3-format}, for example \"Price: %{y:$.2f}\". https://github.com/d3/d3-format/tree/v1.4.5#d3-format for details on the formatting syntax. Dates are formatted using d3-time-format's syntax %{variable|d3-time-format}, for example \"Day: %{2019-01-01|%A}\". https://github.com/d3/d3-time-format/tree/v2.2.3#locale_format for details on the date formatting syntax. Every attributes that can be specified per-point (the ones that are `arrayOk: true`) are available. variable `z`", + "dflt": "", + "editType": "plot", + "valType": "string" + }, "transforms": { "items": { "transform": { @@ -31583,6 +31670,35 @@ "valType": "string" } }, + "textfont": { + "color": { + "dflt": "auto", + "editType": "style", + "valType": "color" + }, + "description": "For this trace it only has an effect if `coloring` is set to *heatmap*. Sets the text font.", + "editType": "plot", + "family": { + "description": "HTML font family - the typeface that will be applied by the web browser. The web browser will only be able to apply a font if it is available on the system which it operates. Provide multiple font families, separated by commas, to indicate the preference in which to apply fonts if they aren't available on the system. The Chart Studio Cloud (at https://chart-studio.plotly.com or on-premise) generates images on a server, where only a select number of fonts are installed and supported. These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*, *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, *PT Sans Narrow*, *Raleway*, *Times New Roman*.", + "editType": "plot", + "noBlank": true, + "strict": true, + "valType": "string" + }, + "role": "object", + "size": { + "dflt": "auto", + "editType": "plot", + "min": 1, + "valType": "number" + } + }, + "texttemplate": { + "description": "For this trace it only has an effect if `coloring` is set to *heatmap*. Template string used for rendering the information text that appear on points. Note that this will override `textinfo`. Variables are inserted using %{variable}, for example \"y: %{y}\". Numbers are formatted using d3-format's syntax %{variable:d3-format}, for example \"Price: %{y:$.2f}\". https://github.com/d3/d3-format/tree/v1.4.5#d3-format for details on the formatting syntax. Dates are formatted using d3-time-format's syntax %{variable|d3-time-format}, for example \"Day: %{2019-01-01|%A}\". https://github.com/d3/d3-time-format/tree/v2.2.3#locale_format for details on the date formatting syntax. Every attributes that can be specified per-point (the ones that are `arrayOk: true`) are available. variables `x`, `y`, `z` and `text`.", + "dflt": "", + "editType": "plot", + "valType": "string" + }, "transforms": { "items": { "transform": {