-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Multi-axis Shapes #7666
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Multi-axis Shapes #7666
Changes from all commits
c8be45f
a7b3bb2
ace820b
a910d42
4d70fd3
d3208e9
e5a71ad
4a571aa
5f7eedf
777cded
0a5093f
de1e72c
e089cdf
be959e9
ef94099
28016cf
13c2866
4cbfb3f
81aab22
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -68,77 +68,142 @@ function handleShapeDefaults(shapeIn, shapeOut, fullLayout) { | |
| var ySizeMode = coerce('ysizemode'); | ||
|
|
||
| // positioning | ||
| var axLetters = ['x', 'y']; | ||
| for (var i = 0; i < 2; i++) { | ||
| var axLetter = axLetters[i]; | ||
| ['x', 'y'].forEach(axLetter => { | ||
| var attrAnchor = axLetter + 'anchor'; | ||
| var sizeMode = axLetter === 'x' ? xSizeMode : ySizeMode; | ||
| var gdMock = { _fullLayout: fullLayout }; | ||
| var ax; | ||
| var pos2r; | ||
| var r2pos; | ||
|
|
||
| // xref, yref | ||
| var axRef = Axes.coerceRef(shapeIn, shapeOut, gdMock, axLetter, undefined, 'paper'); | ||
| var axRefType = Axes.getRefType(axRef); | ||
|
|
||
| if (axRefType === 'range') { | ||
| ax = Axes.getFromId(gdMock, axRef); | ||
| ax._shapeIndices.push(shapeOut._index); | ||
| r2pos = helpers.rangeToShapePosition(ax); | ||
| pos2r = helpers.shapePositionToRange(ax); | ||
| if (ax.type === 'category' || ax.type === 'multicategory') { | ||
| coerce(axLetter + '0shift'); | ||
| coerce(axLetter + '1shift'); | ||
| } | ||
| // xref, yref - handle both string and array values | ||
| var axRef; | ||
| var refAttr = axLetter + 'ref'; | ||
| var inputRef = shapeIn[refAttr]; | ||
|
|
||
| if(Array.isArray(inputRef) && inputRef.length > 0) { | ||
| // Array case: use coerceRefArray for validation | ||
| var expectedLen = helpers.countDefiningCoords(shapeType, path); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't this want to be the count just for |
||
| axRef = Axes.coerceRefArray(shapeIn, shapeOut, gdMock, axLetter, undefined, 'paper', expectedLen); | ||
| shapeOut['_' + axLetter + 'refArray'] = true; | ||
|
|
||
| // Need to register the shape with all referenced axes for redrawing purposes | ||
| axRef.forEach(function(ref) { | ||
| if(Axes.getRefType(ref) === 'range') { | ||
| ax = Axes.getFromId(gdMock, ref); | ||
| if(ax && ax._shapeIndices.indexOf(shapeOut._index) === -1) { | ||
| ax._shapeIndices.push(shapeOut._index); | ||
| } | ||
| } | ||
alexshoe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| }); | ||
| } else { | ||
| pos2r = r2pos = Lib.identity; | ||
| // String/undefined case: use coerceRef | ||
| axRef = Axes.coerceRef(shapeIn, shapeOut, gdMock, axLetter, undefined, 'paper'); | ||
| } | ||
|
|
||
| // Coerce x0, x1, y0, y1 | ||
| if (noPath) { | ||
| var dflt0 = 0.25; | ||
| var dflt1 = 0.75; | ||
|
|
||
| // hack until V3.0 when log has regular range behavior - make it look like other | ||
| // ranges to send to coerce, then put it back after | ||
| // this is all to give reasonable default position behavior on log axes, which is | ||
| // a pretty unimportant edge case so we could just ignore this. | ||
| var attr0 = axLetter + '0'; | ||
| var attr1 = axLetter + '1'; | ||
| var in0 = shapeIn[attr0]; | ||
| var in1 = shapeIn[attr1]; | ||
| shapeIn[attr0] = pos2r(shapeIn[attr0], true); | ||
| shapeIn[attr1] = pos2r(shapeIn[attr1], true); | ||
|
|
||
| if (sizeMode === 'pixel') { | ||
| coerce(attr0, 0); | ||
| coerce(attr1, 10); | ||
| if(Array.isArray(axRef)) { | ||
| var dflts = [0.25, 0.75]; | ||
| var pixelDflts = [0, 10]; | ||
|
|
||
| // For each coordinate, coerce the position with their respective axis ref | ||
| [0, 1].forEach(function(i) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks to me like this whole loop should be skipped for paths - they don't want |
||
| var ref = axRef[i]; | ||
| var refType = Axes.getRefType(ref); | ||
| if(refType === 'range') { | ||
| ax = Axes.getFromId(gdMock, ref); | ||
| pos2r = helpers.shapePositionToRange(ax); | ||
| r2pos = helpers.rangeToShapePosition(ax); | ||
| if(ax.type === 'category' || ax.type === 'multicategory') { | ||
| coerce(axLetter + i + 'shift'); | ||
| } | ||
| } else { | ||
| pos2r = r2pos = Lib.identity; | ||
| } | ||
|
|
||
| if(noPath) { | ||
| var attr = axLetter + i; | ||
| var inValue = shapeIn[attr]; | ||
| shapeIn[attr] = pos2r(shapeIn[attr], true); | ||
|
|
||
| if(sizeMode === 'pixel') { | ||
| coerce(attr, pixelDflts[i]); | ||
| } else { | ||
| Axes.coercePosition(shapeOut, gdMock, coerce, ref, attr, dflts[i]); | ||
| } | ||
|
|
||
| shapeOut[attr] = r2pos(shapeOut[attr]); | ||
| shapeIn[attr] = inValue; | ||
| } | ||
|
|
||
| if(i === 0 && sizeMode === 'pixel') { | ||
| var inAnchor = shapeIn[attrAnchor]; | ||
| shapeIn[attrAnchor] = pos2r(shapeIn[attrAnchor], true); | ||
| Axes.coercePosition(shapeOut, gdMock, coerce, ref, attrAnchor, 0.25); | ||
| shapeOut[attrAnchor] = r2pos(shapeOut[attrAnchor]); | ||
| shapeIn[attrAnchor] = inAnchor; | ||
| } | ||
| }); | ||
| } else { | ||
| var axRefType = Axes.getRefType(axRef); | ||
|
|
||
| if(axRefType === 'range') { | ||
| ax = Axes.getFromId(gdMock, axRef); | ||
| ax._shapeIndices.push(shapeOut._index); | ||
| r2pos = helpers.rangeToShapePosition(ax); | ||
| pos2r = helpers.shapePositionToRange(ax); | ||
| if(ax.type === 'category' || ax.type === 'multicategory') { | ||
| coerce(axLetter + '0shift'); | ||
| coerce(axLetter + '1shift'); | ||
| } | ||
|
Comment on lines
+154
to
+157
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. likewise this shouldn't be done for paths |
||
| } else { | ||
| Axes.coercePosition(shapeOut, gdMock, coerce, axRef, attr0, dflt0); | ||
| Axes.coercePosition(shapeOut, gdMock, coerce, axRef, attr1, dflt1); | ||
| pos2r = r2pos = Lib.identity; | ||
| } | ||
|
|
||
| // hack part 2 | ||
| shapeOut[attr0] = r2pos(shapeOut[attr0]); | ||
| shapeOut[attr1] = r2pos(shapeOut[attr1]); | ||
| shapeIn[attr0] = in0; | ||
| shapeIn[attr1] = in1; | ||
| } | ||
| // Coerce x0, x1, y0, y1 | ||
| if(noPath) { | ||
| var dflt0 = 0.25; | ||
| var dflt1 = 0.75; | ||
|
|
||
| // hack until V3.0 when log has regular range behavior - make it look like other | ||
| // ranges to send to coerce, then put it back after | ||
| // this is all to give reasonable default position behavior on log axes, which is | ||
| // a pretty unimportant edge case so we could just ignore this. | ||
| var attr0 = axLetter + '0'; | ||
| var attr1 = axLetter + '1'; | ||
| var in0 = shapeIn[attr0]; | ||
| var in1 = shapeIn[attr1]; | ||
| shapeIn[attr0] = pos2r(shapeIn[attr0], true); | ||
| shapeIn[attr1] = pos2r(shapeIn[attr1], true); | ||
|
|
||
| if(sizeMode === 'pixel') { | ||
| coerce(attr0, 0); | ||
| coerce(attr1, 10); | ||
| } else { | ||
| Axes.coercePosition(shapeOut, gdMock, coerce, axRef, attr0, dflt0); | ||
| Axes.coercePosition(shapeOut, gdMock, coerce, axRef, attr1, dflt1); | ||
| } | ||
|
|
||
| // hack part 2 | ||
| shapeOut[attr0] = r2pos(shapeOut[attr0]); | ||
| shapeOut[attr1] = r2pos(shapeOut[attr1]); | ||
| shapeIn[attr0] = in0; | ||
| shapeIn[attr1] = in1; | ||
| } | ||
|
|
||
| // Coerce xanchor and yanchor | ||
| if (sizeMode === 'pixel') { | ||
| // Hack for log axis described above | ||
| var inAnchor = shapeIn[attrAnchor]; | ||
| shapeIn[attrAnchor] = pos2r(shapeIn[attrAnchor], true); | ||
| // Coerce xanchor and yanchor | ||
| if(sizeMode === 'pixel') { | ||
| // Hack for log axis described above | ||
| var inAnchor = shapeIn[attrAnchor]; | ||
| shapeIn[attrAnchor] = pos2r(shapeIn[attrAnchor], true); | ||
|
|
||
| Axes.coercePosition(shapeOut, gdMock, coerce, axRef, attrAnchor, 0.25); | ||
| Axes.coercePosition(shapeOut, gdMock, coerce, axRef, attrAnchor, 0.25); | ||
|
|
||
| // Hack part 2 | ||
| shapeOut[attrAnchor] = r2pos(shapeOut[attrAnchor]); | ||
| shapeIn[attrAnchor] = inAnchor; | ||
| // Hack part 2 | ||
| shapeOut[attrAnchor] = r2pos(shapeOut[attrAnchor]); | ||
| shapeIn[attrAnchor] = inAnchor; | ||
| } | ||
| } | ||
| } | ||
| }); | ||
|
|
||
| if (noPath) { | ||
| Lib.noneOrAll(shapeIn, shapeOut, ['x0', 'x1', 'y0', 'y1']); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should be explicit how this applies to each shape type - and in particular that it applies to paths