Skip to content

Commit a008354

Browse files
MFedMFed
MFed
authored and
MFed
committed
Switching absolutetail to axref, ayref based on code review feedback. Can't figure out how the regex for axis ref works, so hardcoded to x,y for now and seeking guidance.
1 parent 8697050 commit a008354

File tree

4 files changed

+79
-48
lines changed

4 files changed

+79
-48
lines changed

src/components/annotations/attributes.js

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -131,31 +131,16 @@ module.exports = {
131131
role: 'style',
132132
description: 'Sets the width (in px) of annotation arrow.'
133133
},
134-
absolutetail: {
135-
valType: 'boolean',
136-
dflt: false,
137-
role: 'style',
138-
description: [
139-
'Indicates if the tail of this arrow is a point in ',
140-
'the coordinate system vs a relative offset in pixels.',
141-
'This is useful for trendline annotations which should ',
142-
'continue to indicate the correct trend when zoomed.',
143-
'If *true*, `ax` is a value on the x axis and `ay` is ',
144-
'a value on the y axis.',
145-
'If *false*, `ax` and `ay` assume their normal offset ',
146-
'roles.'
147-
].join(' ')
148-
},
149134
ax: {
150135
valType: 'number',
151136
dflt: -10,
152137
role: 'info',
153138
description: [
154139
'Sets the x component of the arrow tail about the arrow head.',
155-
'If `absolutetail` is false, a positive (negative) ',
140+
'If `axref` is `pixel`, a positive (negative) ',
156141
'component corresponds to an arrow pointing',
157142
'from right to left (left to right).',
158-
'If `absolutetail` is true, this is a value on the x axis.'
143+
'If `axref` is an axis, this is a value on that axis.'
159144
].join(' ')
160145
},
161146
ay: {
@@ -164,10 +149,44 @@ module.exports = {
164149
role: 'info',
165150
description: [
166151
'Sets the y component of the arrow tail about the arrow head.',
167-
'If `absolutetail` is false, a positive (negative) ',
152+
'If `ayref` is `pixel`, a positive (negative) ',
168153
'component corresponds to an arrow pointing',
169154
'from bottom to top (top to bottom).',
170-
'If `absolutetail` is true, this is a value on the y axis.'
155+
'If `ayref` is an axis, this is a value on that axis.'
156+
].join(' ')
157+
},
158+
axref: {
159+
valType: 'enumerated',
160+
dflt: 'pixel',
161+
values: [
162+
'pixel',
163+
'x'
164+
],
165+
role: 'info',
166+
description: [
167+
'Indicates in what terms the tail of the annotation (ax,ay) ',
168+
'is specified. If `pixel`, `ax` is a relative offset in pixels ',
169+
'from `x`. If set to an x axis id (e.g. *x* or *x2*), `ax` is ',
170+
'specified in the same terms as that axis. This is useful ',
171+
'for trendline annotations which should continue to indicate ',
172+
'the correct trend when zoomed.'
173+
].join(' ')
174+
},
175+
ayref: {
176+
valType: 'enumerated',
177+
dflt: 'pixel',
178+
values: [
179+
'pixel',
180+
'y'
181+
],
182+
role: 'info',
183+
description: [
184+
'Indicates in what terms the tail of the annotation (ax,ay) ',
185+
'is specified. If `pixel`, `ay` is a relative offset in pixels ',
186+
'from `y`. If set to a y axis id (e.g. *y* or *y2*), `ay` is ',
187+
'specified in the same terms as that axis. This is useful ',
188+
'for trendline annotations which should continue to indicate ',
189+
'the correct trend when zoomed.'
171190
].join(' ')
172191
},
173192
// positioning

src/components/annotations/index.js

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ function handleAnnotationDefaults(annIn, fullLayout) {
5959
coerce('arrowwidth', ((borderOpacity && borderWidth) || 1) * 2);
6060
coerce('ax');
6161
coerce('ay');
62-
coerce('absolutetail');
62+
coerce('axref');
63+
coerce('ayref');
6364

6465
// if you have one part of arrow length you should have both
6566
Lib.noneOrAll(annIn, annOut, ['ax', 'ay']);
@@ -91,7 +92,7 @@ function handleAnnotationDefaults(annIn, fullLayout) {
9192
newval = Lib.dateTime2ms(annIn[axLetter]);
9293
if(newval !== false) annIn[axLetter] = newval;
9394

94-
if(annIn.absolutetail) {
95+
if(annIn['a' + axLetter + 'ref'] === axRef) {
9596
var newvalB = Lib.dateTime2ms(annIn['a' + axLetter]);
9697
if(newvalB !== false) annIn['a' + axLetter] = newvalB;
9798
}
@@ -425,8 +426,8 @@ annotations.draw = function(gd, index, opt, value) {
425426

426427
var annotationIsOffscreen = false;
427428
['x', 'y'].forEach(function(axLetter) {
428-
var ax = Axes.getFromId(gd,
429-
options[axLetter + 'ref'] || axLetter),
429+
var axRef = options[axLetter + 'ref'] || axLetter,
430+
ax = Axes.getFromId(gd, axRef),
430431
dimAngle = (textangle + (axLetter === 'x' ? 0 : 90)) * Math.PI / 180,
431432
annSize = outerwidth * Math.abs(Math.cos(dimAngle)) +
432433
outerheight * Math.abs(Math.sin(dimAngle)),
@@ -456,7 +457,7 @@ annotations.draw = function(gd, index, opt, value) {
456457
}
457458

458459
var alignShift = 0;
459-
if(options.absolutetail) {
460+
if(options['a' + axLetter + 'ref'] === axRef) {
460461
annPosPx['aa' + axLetter] = ax._offset + ax.l2p(options['a' + axLetter]);
461462
} else {
462463
if(options.showarrow) {
@@ -486,13 +487,15 @@ annotations.draw = function(gd, index, opt, value) {
486487
// make sure the arrowhead (if there is one)
487488
// and the annotation center are visible
488489
if(options.showarrow) {
489-
if (options.absolutetail) {
490+
if(options.axref === options.xref)
490491
arrowX = Lib.constrain(annPosPx.x, 1, fullLayout.width - 1);
491-
arrowY = Lib.constrain(annPosPx.y, 1, fullLayout.height - 1);
492-
} else {
492+
else
493493
arrowX = Lib.constrain(annPosPx.x - options.ax, 1, fullLayout.width - 1);
494+
495+
if(options.ayref === options.yref)
496+
arrowY = Lib.constrain(annPosPx.y, 1, fullLayout.height - 1);
497+
else
494498
arrowY = Lib.constrain(annPosPx.y - options.ay, 1, fullLayout.height - 1);
495-
}
496499
}
497500
annPosPx.x = Lib.constrain(annPosPx.x, 1, fullLayout.width - 1);
498501
annPosPx.y = Lib.constrain(annPosPx.y, 1, fullLayout.height - 1);
@@ -512,13 +515,15 @@ annotations.draw = function(gd, index, opt, value) {
512515
outerwidth - borderwidth, outerheight - borderwidth);
513516

514517
var annX = 0, annY = 0;
515-
if(options.absolutetail) {
518+
if(options.axref === options.xref)
516519
annX = Math.round(annPosPx.aax - outerwidth / 2);
517-
annY = Math.round(annPosPx.aay - outerheight / 2);
518-
} else {
520+
else
519521
annX = Math.round(annPosPx.x - outerwidth / 2);
522+
523+
if(options.ayref === options.yref)
524+
annY = Math.round(annPosPx.aay - outerheight / 2);
525+
else
520526
annY = Math.round(annPosPx.y - outerheight / 2);
521-
}
522527

523528
ann.call(Lib.setTranslate, annX, annY);
524529

@@ -539,13 +544,15 @@ annotations.draw = function(gd, index, opt, value) {
539544
// how-to-get-the-width-of-an-svg-tspan-element
540545
var arrowX0, arrowY0;
541546

542-
if(options.absolutetail) {
547+
if(options.axref === options.xref)
543548
arrowX0 = annPosPx.aax + dx;
544-
arrowY0 = annPosPx.aay + dy;
545-
} else {
549+
else
546550
arrowX0 = annPosPx.x + dx;
551+
552+
if(options.ayref === options.yref)
553+
arrowY0 = annPosPx.aay + dy;
554+
else
547555
arrowY0 = annPosPx.y + dy;
548-
}
549556

550557
// create transform matrix and related functions
551558
var transform =
@@ -648,14 +655,15 @@ annotations.draw = function(gd, index, opt, value) {
648655
(options.y + dy / ya._m) :
649656
(1 - ((arrowY + dy - gs.t) / gs.h));
650657

651-
if(options.absolutetail) {
658+
if(options.axref === options.xref)
652659
update[annbase + '.ax'] = xa ?
653660
(options.ax + dx / xa._m) :
654661
((arrowX + dx - gs.l) / gs.w);
662+
663+
if(options.ayref === options.yref)
655664
update[annbase + '.ay'] = ya ?
656665
(options.ay + dy / ya._m) :
657666
(1 - ((arrowY + dy - gs.t) / gs.h));
658-
}
659667

660668
anng.attr({
661669
transform: 'rotate(' + textangle + ',' +
@@ -698,13 +706,16 @@ annotations.draw = function(gd, index, opt, value) {
698706
ann.call(Lib.setTranslate, x0 + dx, y0 + dy);
699707
var csr = 'pointer';
700708
if(options.showarrow) {
701-
if(options.absolutetail) {
709+
if(options.axref === options.xref)
702710
update[annbase + '.ax'] = xa.p2l(xa.l2p(options.ax) + dx);
703-
update[annbase + '.ay'] = ya.p2l(ya.l2p(options.ay) + dy);
704-
} else {
711+
else
705712
update[annbase + '.ax'] = options.ax + dx;
713+
714+
if(options.ayref === options.yref)
715+
update[annbase + '.ay'] = ya.p2l(ya.l2p(options.ay) + dy);
716+
else
706717
update[annbase + '.ay'] = options.ay + dy;
707-
}
718+
708719
drawArrow(dx, dy);
709720
}
710721
else {

test/image/mocks/annotations.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"font":{"color":"rgb(0, 0, 255)","size":20},
4343
"arrowcolor":"rgb(166, 28, 0)","borderpad":3,"textangle":50,"x":5,"y":1
4444
},
45-
{"text":"","showarrow":true,"borderwidth":1.2,"arrowhead":2,"absolutetail":true,"x":5,"y":5,"ax":4,"ay":3}
45+
{"text":"","showarrow":true,"borderwidth":1.2,"arrowhead":2,"axref":"x","ayref":"y","x":5,"y":5,"ax":4,"ay":3}
4646
]
4747
}
4848
}

test/jasmine/tests/annotations_test.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
var PlotlyInternal = require('@src/plotly');
1+
require('@src/plotly');
22
var Plots = require('@src/plots/plots');
33
var Annotations = require('@src/components/annotations');
44

@@ -7,21 +7,22 @@ describe('Test annotations', function() {
77
'use strict';
88

99
describe('supplyLayoutDefaults', function() {
10-
it('should default to not use absolute arrow tail', function() {
10+
it('should default to pixel for axref/ayref', function() {
1111
var annotationDefaults = {};
1212
annotationDefaults._has = Plots._hasPlotType.bind(annotationDefaults);
1313

1414
Annotations.supplyLayoutDefaults({ annotations: [{ showarrow: true, arrowhead: 2}] }, annotationDefaults);
1515

16-
expect(annotationDefaults.annotations[0].absolutetail).toBe(false);
16+
expect(annotationDefaults.annotations[0].axref).toEqual('pixel');
17+
expect(annotationDefaults.annotations[0].ayref).toEqual('pixel');
1718
});
1819

19-
it('should convert ax/ay date coordinates to milliseconds if absolutetail is true', function() {
20+
it('should convert ax/ay date coordinates to milliseconds if tail is in axis terms and axis is a date', function() {
2021
var annotationOut = { xaxis: { type: 'date', range: ['2000-01-01', '2016-01-01'] }};
2122
annotationOut._has = Plots._hasPlotType.bind(annotationOut);
2223

2324
var annotationIn = {
24-
annotations: [{ showarrow: true, absolutetail: true, x: '2008-07-01', ax: '2004-07-01', y: 0, ay: 50}]
25+
annotations: [{ showarrow: true, axref: 'x', ayref: 'y', x: '2008-07-01', ax: '2004-07-01', y: 0, ay: 50}]
2526
};
2627

2728
Annotations.supplyLayoutDefaults(annotationIn, annotationOut);

0 commit comments

Comments
 (0)