Skip to content

Commit 7cfba36

Browse files
committed
fix 3d annotations on type: 'category' axes
- coerce (x, y, z) in scene.plot after the ax._categories is filled - use .r2l to update annotation position - could be cleaned up (by e.g. wrapping the 3d annotation default into a required subroutine).
1 parent ababc49 commit 7cfba36

File tree

2 files changed

+49
-28
lines changed

2 files changed

+49
-28
lines changed

src/plots/gl3d/layout/defaults.js

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
var Lib = require('../../../lib');
1313
var Color = require('../../../components/color');
14-
var Axes = require('../../cartesian/axes');
1514

1615
var handleSubplotDefaults = require('../../subplot_defaults');
1716
var handleArrayContainerDefaults = require('../../array_container_defaults');
@@ -111,33 +110,19 @@ function handleGl3dDefaults(sceneLayoutIn, sceneLayoutOut, coerce, opts) {
111110
}
112111

113112
function handleAnnotationDefaults(annIn, annOut, sceneLayout, opts, itemOpts) {
114-
115113
function coerce(attr, dflt) {
116114
return Lib.coerce(annIn, annOut, layoutAttributes.annotations, attr, dflt);
117115
}
118116

119-
function coercePosition(axLetter) {
120-
var axName = axLetter + 'axis';
121-
var gdMock = { _fullLayout: {} };
122-
123-
// mock in such way that getFromId grabs correct 3D axis
124-
gdMock._fullLayout[axName] = sceneLayout[axName];
125-
126-
// hard-set here for completeness
127-
annOut[axLetter + 'ref'] = axLetter;
128-
129-
return Axes.coercePosition(annOut, gdMock, coerce, axLetter, axLetter, 0.5);
130-
}
131-
132117
var visible = coerce('visible', !itemOpts.itemIsNotPlainObject);
133118
if(!visible) return annOut;
134119

135120
coerce('opacity');
136121
coerce('align');
137122
coerce('bgcolor');
138123

139-
var borderColor = coerce('bordercolor'),
140-
borderOpacity = Color.opacity(borderColor);
124+
var borderColor = coerce('bordercolor');
125+
var borderOpacity = Color.opacity(borderColor);
141126

142127
coerce('borderpad');
143128

@@ -154,13 +139,21 @@ function handleAnnotationDefaults(annIn, annOut, sceneLayout, opts, itemOpts) {
154139
var h = coerce('height');
155140
if(h) coerce('valign');
156141

157-
coercePosition('x');
158-
coercePosition('y');
159-
coercePosition('z');
142+
// Do not use Axes.coercePosition here
143+
// as ax._categories aren't filled in at this stage,
144+
// Axes.coercePosition is called during scene.setConvert instead
145+
coerce('x');
146+
coerce('y');
147+
coerce('z');
160148

161149
// if you have one coordinate you should all three
162150
Lib.noneOrAll(annIn, annOut, ['x', 'y', 'z']);
163151

152+
// hard-set here for completeness
153+
annOut.xref = 'x';
154+
annOut.yref = 'y';
155+
annOut.zref = 'z';
156+
164157
coerce('xanchor');
165158
coerce('yanchor');
166159
coerce('xshift');

src/plots/gl3d/scene.js

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ var project = require('./project');
2626
var createAxesOptions = require('./layout/convert');
2727
var createSpikeOptions = require('./layout/spikes');
2828
var computeTickMarks = require('./layout/tick_marks');
29+
var layoutAttributes = require('./layout/layout_attributes');
2930

3031
var STATIC_CANVAS, STATIC_CONTEXT;
3132

@@ -396,6 +397,9 @@ proto.plot = function(sceneData, fullLayout, layout) {
396397
// Save scale
397398
this.dataScale = dataScale;
398399

400+
// after computeTraceBounds where ax._categories are filled in
401+
this.updateAnnotations();
402+
399403
// Update traces
400404
for(i = 0; i < sceneData.length; ++i) {
401405
data = sceneData[i];
@@ -719,16 +723,17 @@ proto.toImage = function(format) {
719723
};
720724

721725
proto.setConvert = function() {
722-
var i;
723-
724-
for(i = 0; i < 3; i++) {
726+
for(var i = 0; i < 3; i++) {
725727
var ax = this.fullSceneLayout[axisProperties[i]];
726728
Axes.setConvert(ax, this.fullLayout);
727729
ax.setScale = Lib.noop;
728730
}
731+
};
729732

733+
proto.updateAnnotations = function() {
730734
var anns = this.fullSceneLayout.annotations;
731-
for(i = 0; i < anns.length; i++) {
735+
736+
for(var i = 0; i < anns.length; i++) {
732737
mockAnnAxes(anns[i], this);
733738
}
734739

@@ -750,7 +755,9 @@ proto.handleAnnotations = function() {
750755

751756
for(var j = 0; j < 3; j++) {
752757
var axLetter = axLetters[j];
753-
var posFraction = fullSceneLayout[axLetter + 'axis'].r2fraction(ann[axLetter]);
758+
var pos = ann[axLetter];
759+
var ax = fullSceneLayout[axLetter + 'axis'];
760+
var posFraction = ax.r2fraction(pos);
754761

755762
if(posFraction < 0 || posFraction > 1) {
756763
annotationIsOffscreen = true;
@@ -764,9 +771,9 @@ proto.handleAnnotations = function() {
764771
.remove();
765772
} else {
766773
ann.pdata = project(this.glplot.cameraParams, [
767-
fullSceneLayout.xaxis.d2l(ann.x) * dataScale[0],
768-
fullSceneLayout.yaxis.d2l(ann.y) * dataScale[1],
769-
fullSceneLayout.zaxis.d2l(ann.z) * dataScale[2]
774+
fullSceneLayout.xaxis.r2l(ann.x) * dataScale[0],
775+
fullSceneLayout.yaxis.r2l(ann.y) * dataScale[1],
776+
fullSceneLayout.zaxis.r2l(ann.z) * dataScale[2]
770777
]);
771778

772779
drawAnnotation(this.graphDiv, ann, i, ann._xa, ann._ya);
@@ -807,6 +814,27 @@ function mockAnnAxes(ann, scene) {
807814
ann._ya.l2p = function() {
808815
return 0.5 * (1 - ann.pdata[1] / ann.pdata[3]) * size.h * (domain.y[1] - domain.y[0]);
809816
};
817+
818+
// or do something more similar to 2d
819+
// where Annotations.supplyLayoutDefaults is called after in Plots.doCalcdata
820+
// if category axes are found.
821+
function coerce(attr, dflt) {
822+
return Lib.coerce(ann, ann, layoutAttributes.annotations, attr, dflt);
823+
}
824+
825+
function coercePosition(axLetter) {
826+
var axName = axLetter + 'axis';
827+
828+
// mock in such way that getFromId grabs correct 3D axis
829+
var gdMock = { _fullLayout: {} };
830+
gdMock._fullLayout[axName] = fullSceneLayout[axName];
831+
832+
return Axes.coercePosition(ann, gdMock, coerce, axLetter, axLetter, 0.5);
833+
}
834+
835+
coercePosition('x');
836+
coercePosition('y');
837+
coercePosition('z');
810838
}
811839

812840
module.exports = Scene;

0 commit comments

Comments
 (0)