@@ -72,9 +72,14 @@ function drawOne(gd, index) {
72
72
var optionsIn = ( layout . annotations || [ ] ) [ index ] ,
73
73
options = fullLayout . annotations [ index ] ;
74
74
75
+ var annClipID = 'clip' + fullLayout . _uid + '_ann' + index ;
76
+
75
77
// this annotation is gone - quit now after deleting it
76
78
// TODO: use d3 idioms instead of deleting and redrawing every time
77
- if ( ! optionsIn || options . visible === false ) return ;
79
+ if ( ! optionsIn || options . visible === false ) {
80
+ d3 . selectAll ( '#' + annClipID ) . remove ( ) ;
81
+ return ;
82
+ }
78
83
79
84
var xa = Axes . getFromId ( gd , options . xref ) ,
80
85
ya = Axes . getFromId ( gd , options . yref ) ,
@@ -118,6 +123,18 @@ function drawOne(gd, index) {
118
123
. call ( Color . stroke , options . bordercolor )
119
124
. call ( Color . fill , options . bgcolor ) ;
120
125
126
+ var isSizeConstrained = options . width || options . height ;
127
+
128
+ var annTextClip = fullLayout . _defs . select ( '.clips' )
129
+ . selectAll ( '#' + annClipID )
130
+ . data ( isSizeConstrained ? [ 0 ] : [ ] ) ;
131
+
132
+ annTextClip . enter ( ) . append ( 'clipPath' )
133
+ . classed ( 'annclip' , true )
134
+ . attr ( 'id' , annClipID )
135
+ . append ( 'rect' ) ;
136
+ annTextClip . exit ( ) . remove ( ) ;
137
+
121
138
var font = options . font ;
122
139
123
140
var annText = annTextGroupInner . append ( 'text' )
@@ -144,19 +161,21 @@ function drawOne(gd, index) {
144
161
// at the end, even if their position changes
145
162
annText . selectAll ( 'tspan.line' ) . attr ( { y : 0 , x : 0 } ) ;
146
163
147
- var mathjaxGroup = annTextGroupInner . select ( '.annotation-math-group' ) ,
148
- hasMathjax = ! mathjaxGroup . empty ( ) ,
149
- anntextBB = Drawing . bBox (
150
- ( hasMathjax ? mathjaxGroup : annText ) . node ( ) ) ,
151
- annwidth = anntextBB . width ,
152
- annheight = anntextBB . height ,
153
- outerwidth = Math . round ( annwidth + 2 * borderfull ) ,
154
- outerheight = Math . round ( annheight + 2 * borderfull ) ;
164
+ var mathjaxGroup = annTextGroupInner . select ( '.annotation-math-group' ) ;
165
+ var hasMathjax = ! mathjaxGroup . empty ( ) ;
166
+ var anntextBB = Drawing . bBox (
167
+ ( hasMathjax ? mathjaxGroup : annText ) . node ( ) ) ;
168
+ var textWidth = anntextBB . width ;
169
+ var textHeight = anntextBB . height ;
170
+ var annWidth = options . width || textWidth ;
171
+ var annHeight = options . height || textHeight ;
172
+ var outerWidth = Math . round ( annWidth + 2 * borderfull ) ;
173
+ var outerHeight = Math . round ( annHeight + 2 * borderfull ) ;
155
174
156
175
157
176
// save size in the annotation object for use by autoscale
158
- options . _w = annwidth ;
159
- options . _h = annheight ;
177
+ options . _w = annWidth ;
178
+ options . _h = annHeight ;
160
179
161
180
function shiftFraction ( v , anchor ) {
162
181
if ( anchor === 'auto' ) {
@@ -181,8 +200,8 @@ function drawOne(gd, index) {
181
200
ax = Axes . getFromId ( gd , axRef ) ,
182
201
dimAngle = ( textangle + ( axLetter === 'x' ? 0 : - 90 ) ) * Math . PI / 180 ,
183
202
// note that these two can be either positive or negative
184
- annSizeFromWidth = outerwidth * Math . cos ( dimAngle ) ,
185
- annSizeFromHeight = outerheight * Math . sin ( dimAngle ) ,
203
+ annSizeFromWidth = outerWidth * Math . cos ( dimAngle ) ,
204
+ annSizeFromHeight = outerHeight * Math . sin ( dimAngle ) ,
186
205
// but this one is the positive total size
187
206
annSize = Math . abs ( annSizeFromWidth ) + Math . abs ( annSizeFromHeight ) ,
188
207
anchor = options [ axLetter + 'anchor' ] ,
@@ -299,22 +318,43 @@ function drawOne(gd, index) {
299
318
return ;
300
319
}
301
320
321
+ var xShift = 0 ;
322
+ var yShift = 0 ;
323
+
324
+ if ( options . align !== 'left' ) {
325
+ xShift = ( annWidth - textWidth ) * ( options . align === 'center' ? 0.5 : 1 ) ;
326
+ }
327
+ if ( options . valign !== 'top' ) {
328
+ yShift = ( annHeight - textHeight ) * ( options . valign === 'middle' ? 0.5 : 1 ) ;
329
+ }
330
+
302
331
if ( hasMathjax ) {
303
- mathjaxGroup . select ( 'svg' ) . attr ( { x : borderfull - 1 , y : borderfull } ) ;
332
+ mathjaxGroup . select ( 'svg' ) . attr ( {
333
+ x : borderfull + xShift - 1 ,
334
+ y : borderfull + yShift
335
+ } )
336
+ . call ( Drawing . setClipUrl , isSizeConstrained ? annClipID : null ) ;
304
337
}
305
338
else {
306
- var texty = borderfull - anntextBB . top ,
307
- textx = borderfull - anntextBB . left ;
308
- annText . attr ( { x : textx , y : texty } ) ;
339
+ var texty = borderfull + yShift - anntextBB . top ,
340
+ textx = borderfull + xShift - anntextBB . left ;
341
+ annText . attr ( {
342
+ x : textx ,
343
+ y : texty
344
+ } )
345
+ . call ( Drawing . setClipUrl , isSizeConstrained ? annClipID : null ) ;
309
346
annText . selectAll ( 'tspan.line' ) . attr ( { y : texty , x : textx } ) ;
310
347
}
311
348
349
+ annTextClip . select ( 'rect' ) . call ( Drawing . setRect , borderfull , borderfull ,
350
+ annWidth , annHeight ) ;
351
+
312
352
annTextBG . call ( Drawing . setRect , borderwidth / 2 , borderwidth / 2 ,
313
- outerwidth - borderwidth , outerheight - borderwidth ) ;
353
+ outerWidth - borderwidth , outerHeight - borderwidth ) ;
314
354
315
355
annTextGroupInner . call ( Drawing . setTranslate ,
316
- Math . round ( annPosPx . x . text - outerwidth / 2 ) ,
317
- Math . round ( annPosPx . y . text - outerheight / 2 ) ) ;
356
+ Math . round ( annPosPx . x . text - outerWidth / 2 ) ,
357
+ Math . round ( annPosPx . y . text - outerHeight / 2 ) ) ;
318
358
319
359
/*
320
360
* rotate text and background
0 commit comments