diff --git a/src/components/fx/hover.js b/src/components/fx/hover.js
index 3b5e15e0ced..1b365338205 100644
--- a/src/components/fx/hover.js
+++ b/src/components/fx/hover.js
@@ -934,10 +934,24 @@ function createHoverText(hoverData, opts, gd) {
}
}
+ var xLetter = 'x';
+ var yLetter = 'y';
+ var zLetter = 'z';
+
+ if(gd._fullLayout.scene) {
+ xLetter = gd._fullLayout.scene.xaxis.hovertitle || xLetter;
+ yLetter = gd._fullLayout.scene.yaxis.hovertitle || yLetter;
+ zLetter = gd._fullLayout.scene.zaxis.hovertitle || zLetter;
+ }
+ else if(!gd._fullLayout.ternary && !gd._fullLayout.title) {
+ xLetter = gd._fullLayout.xaxis.hovertitle || xLetter;
+ yLetter = gd._fullLayout.yaxis.hovertitle || yLetter;
+ }
+
if(d.zLabel !== undefined) {
- if(d.xLabel !== undefined) text += 'x: ' + d.xLabel + '
';
- if(d.yLabel !== undefined) text += 'y: ' + d.yLabel + '
';
- text += (text ? 'z: ' : '') + d.zLabel;
+ if(d.xLabel !== undefined) text += xLetter + ': ' + d.xLabel + '
';
+ if(d.yLabel !== undefined) text += yLetter + ': ' + d.yLabel + '
';
+ text += (text ? zLetter + ': ' : '') + d.zLabel;
}
else if(showCommonLabel && d[hovermode + 'Label'] === t0) {
text = d[(hovermode === 'x' ? 'y' : 'x') + 'Label'] || '';
diff --git a/src/plots/cartesian/axis_defaults.js b/src/plots/cartesian/axis_defaults.js
index 2269152de39..aceec3c2064 100644
--- a/src/plots/cartesian/axis_defaults.js
+++ b/src/plots/cartesian/axis_defaults.js
@@ -56,7 +56,10 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce,
handleCategoryOrderDefaults(containerIn, containerOut, coerce, options);
- if(axType !== 'category' && !options.noHover) coerce('hoverformat');
+ if(axType !== 'category' && !options.noHover) {
+ coerce('hoverformat');
+ coerce('hovertitle', options.dfltHoverTitle);
+ }
if(!visible) return containerOut;
diff --git a/src/plots/cartesian/layout_attributes.js b/src/plots/cartesian/layout_attributes.js
index ae48118491e..92fc412d793 100644
--- a/src/plots/cartesian/layout_attributes.js
+++ b/src/plots/cartesian/layout_attributes.js
@@ -593,6 +593,14 @@ module.exports = {
'*%H~%M~%S.%2f* would display *09~15~23.46*'
].join(' ')
},
+ hovertitle: {
+ valType: 'string',
+ role: 'info',
+ editType: 'none',
+ description: [
+ 'Sets axis title(s) to be displayed in the hovering popup'
+ ].join(' ')
+ },
// lines and grids
showline: {
valType: 'boolean',
diff --git a/src/plots/cartesian/layout_defaults.js b/src/plots/cartesian/layout_defaults.js
index 2a59a1bb428..4cbe3403a58 100644
--- a/src/plots/cartesian/layout_defaults.js
+++ b/src/plots/cartesian/layout_defaults.js
@@ -167,6 +167,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
var defaultOptions = {
letter: axLetter,
+ dfltHoverTitle: axLetter,
font: layoutOut.font,
outerTicks: outerTicks[axName],
showGrid: !noGrids[axName],
diff --git a/src/plots/gl3d/layout/axis_attributes.js b/src/plots/gl3d/layout/axis_attributes.js
index 7264cf521fb..f1810fd9976 100644
--- a/src/plots/gl3d/layout/axis_attributes.js
+++ b/src/plots/gl3d/layout/axis_attributes.js
@@ -103,6 +103,7 @@ module.exports = overrideAll({
tickformat: axesAttrs.tickformat,
tickformatstops: axesAttrs.tickformatstops,
hoverformat: axesAttrs.hoverformat,
+ hovertitle: axesAttrs.hovertitle,
// lines and grids
showline: axesAttrs.showline,
linecolor: axesAttrs.linecolor,
diff --git a/src/plots/polar/layout_attributes.js b/src/plots/polar/layout_attributes.js
index f6905453dd9..92d4ce80cd7 100644
--- a/src/plots/polar/layout_attributes.js
+++ b/src/plots/polar/layout_attributes.js
@@ -118,6 +118,7 @@ var radialAxisAttrs = {
// might need a 'titleside' and even 'titledirection' down the road
hoverformat: axesAttrs.hoverformat,
+ hovertitle: axesAttrs.hovertitle,
uirevision: {
valType: 'any',
@@ -234,6 +235,7 @@ var angularAxisAttrs = {
},
hoverformat: axesAttrs.hoverformat,
+ hovertitle: axesAttrs.hovertitle,
uirevision: {
valType: 'any',
diff --git a/src/plots/ternary/layout_attributes.js b/src/plots/ternary/layout_attributes.js
index effa824be8d..13948d130cb 100644
--- a/src/plots/ternary/layout_attributes.js
+++ b/src/plots/ternary/layout_attributes.js
@@ -42,6 +42,7 @@ var ternaryAxesAttrs = {
tickformat: axesAttrs.tickformat,
tickformatstops: axesAttrs.tickformatstops,
hoverformat: axesAttrs.hoverformat,
+ hovertitle: axesAttrs.hovertitle,
// lines and grids
showline: extendFlat({}, axesAttrs.showline, {dflt: true}),
linecolor: axesAttrs.linecolor,
diff --git a/src/plots/ternary/layout_defaults.js b/src/plots/ternary/layout_defaults.js
index 7ab47dee7ac..0d77ee715af 100644
--- a/src/plots/ternary/layout_defaults.js
+++ b/src/plots/ternary/layout_defaults.js
@@ -126,5 +126,6 @@ function handleAxisDefaults(containerIn, containerOut, options, ternaryLayoutOut
});
coerce('hoverformat');
+ coerce('hovertitle');
coerce('layer');
}
diff --git a/test/image/baselines/gl3d_surface_after_heatmap.png b/test/image/baselines/gl3d_surface_after_heatmap.png
index e2e84ff714a..06bd02e3df2 100644
Binary files a/test/image/baselines/gl3d_surface_after_heatmap.png and b/test/image/baselines/gl3d_surface_after_heatmap.png differ
diff --git a/test/image/mocks/gl3d_surface_after_heatmap.json b/test/image/mocks/gl3d_surface_after_heatmap.json
index bd34b7f8c70..da6b4a4cf37 100644
--- a/test/image/mocks/gl3d_surface_after_heatmap.json
+++ b/test/image/mocks/gl3d_surface_after_heatmap.json
@@ -2,28 +2,72 @@
"data": [
{
"type": "heatmap",
- "x": [0, 1, 2],
- "y": [0, 1, 2],
+ "zsmooth": "best",
+ "x": [0, 1, 2, 3, 4],
+ "y": [0, 1, 2, 3, 4],
"z": [
- [0, 1, 0],
- [1, 0, 1],
- [0, 1, 0]
+ [0, 1, 0, 1, 0],
+ [1, 0.25, 0.75, 0.25, 1],
+ [0, 0.75, 0.25, 0.75, 0],
+ [1, 0.25, 0.75, 0.25, 1],
+ [0, 1, 0, 1, 0]
]
},
{
"type": "surface",
- "x": [0, 1, 2],
- "y": [0, 1, 2],
+ "x": [0, 1, 2, 3, 4],
+ "y": [0, 1, 2, 3, 4],
"z": [
- [0, 1, 0],
- [1, 0, 1],
- [0, 1, 0]
+ [0, 1, 0, 1, 0],
+ [1, 0.25, 0.75, 0.25, 1],
+ [0, 0.75, 0.25, 0.75, 0],
+ [1, 0.25, 0.75, 0.25, 1],
+ [0, 1, 0, 1, 0]
]
}
],
"layout": {
"title": "Surface 3d plot on top of 2d heatmap!",
"width": 600,
- "height": 400
+ "height": 400,
+ "xaxis": {
+ "hovertitle": "lon",
+ "title": {
+ "text": "Longitude"
+ }
+ },
+ "yaxis": {
+ "hovertitle": "lat",
+ "title": {
+ "text": "Latitude"
+ }
+ },
+ "scene": {
+ "xaxis": {
+ "hovertitle": "lon",
+ "title": {
+ "text": "Longitude"
+ }
+ },
+ "yaxis": {
+ "hovertitle": "lat",
+ "title": {
+ "text": "Latitude"
+ }
+ },
+ "zaxis": {
+ "hovertitle": "alt",
+ "title": {
+ "text": "Altitude"
+ }
+ },
+ "camera": {
+ "eye": {
+ "x": 2,
+ "y": 2,
+ "z": 2
+ }
+ }
+ }
}
}
diff --git a/test/image/mocks/polar_wind-rose.json b/test/image/mocks/polar_wind-rose.json
index fb40daa5592..cf37ab28b66 100644
--- a/test/image/mocks/polar_wind-rose.json
+++ b/test/image/mocks/polar_wind-rose.json
@@ -31,8 +31,8 @@
"polar": {
"barmode": "overlay",
"bargap": 0,
- "radialaxis": {"ticksuffix": "%", "angle": 45, "dtick": 20},
- "angularaxis": {"direction": "clockwise"}
+ "radialaxis": {"hovertitle": "likelihood", "ticksuffix": "%", "angle": 45, "dtick": 20},
+ "angularaxis": {"hovertitle": "direction", "direction": "clockwise"}
}
}
}