@@ -184,27 +184,42 @@ module.exports = function draw(gd) {
184
184
if ( anchorUtils . isRightAnchor ( opts ) ) {
185
185
lx -= opts . width ;
186
186
}
187
- if ( anchorUtils . isCenterAnchor ( opts ) ) {
187
+ else if ( anchorUtils . isCenterAnchor ( opts ) ) {
188
188
lx -= opts . width / 2 ;
189
189
}
190
190
191
191
if ( anchorUtils . isBottomAnchor ( opts ) ) {
192
192
ly -= opts . height ;
193
193
}
194
- if ( anchorUtils . isMiddleAnchor ( opts ) ) {
194
+ else if ( anchorUtils . isMiddleAnchor ( opts ) ) {
195
195
ly -= opts . height / 2 ;
196
196
}
197
197
198
+ lx = Math . round ( lx ) ;
199
+ ly = Math . round ( ly ) ;
200
+
201
+ // Make sure the legend top is below the top margin
202
+ if ( ly < fullLayout . margin . t ) ly = fullLayout . margin . t ;
203
+
204
+ var scrollHeightMax = fullLayout . height - fullLayout . margin . b - ly ;
205
+ var scrollHeight = Math . min ( scrollHeightMax , opts . height ) ;
206
+
207
+ if ( scrollHeight <= 2 * opts . borderwidth ) {
208
+ console . error ( 'Legend.draw: insufficient space to draw legend' ) ;
209
+ legend . remove ( ) ;
210
+ return ;
211
+ }
212
+
198
213
// Deal with scrolling
199
- var plotHeight = fullLayout . height - fullLayout . margin . b ,
200
- scrollheight = Math . min ( plotHeight - ly , opts . height ) ,
201
- scrollPosition = scrollBox . attr ( 'data-scroll' ) ? scrollBox . attr ( 'data-scroll' ) : 0 ;
214
+ var scrollPosition = scrollBox . attr ( 'data-scroll' ) ?
215
+ scrollBox . attr ( 'data-scroll' ) :
216
+ 0 ;
202
217
203
218
scrollBox . attr ( 'transform' , 'translate(0, ' + scrollPosition + ')' ) ;
204
219
205
220
bg . attr ( {
206
221
width : opts . width - 2 * opts . borderwidth ,
207
- height : scrollheight - 2 * opts . borderwidth ,
222
+ height : scrollHeight - 2 * opts . borderwidth ,
208
223
x : opts . borderwidth ,
209
224
y : opts . borderwidth
210
225
} ) ;
@@ -213,15 +228,15 @@ module.exports = function draw(gd) {
213
228
214
229
clipPath . select ( 'rect' ) . attr ( {
215
230
width : opts . width ,
216
- height : scrollheight ,
231
+ height : scrollHeight ,
217
232
x : 0 ,
218
233
y : 0
219
234
} ) ;
220
235
221
236
legend . call ( Drawing . setClipUrl , clipId ) ;
222
237
223
238
// If scrollbar should be shown.
224
- if ( opts . height - scrollheight > 0 && ! gd . _context . staticPlot ) {
239
+ if ( opts . height - scrollHeight > 0 && ! gd . _context . staticPlot ) {
225
240
226
241
bg . attr ( {
227
242
width : opts . width - 2 * opts . borderwidth + constants . scrollBarWidth
@@ -243,21 +258,21 @@ module.exports = function draw(gd) {
243
258
scrollBox . attr ( 'data-scroll' , 0 ) ;
244
259
}
245
260
246
- scrollHandler ( 0 , scrollheight ) ;
261
+ scrollHandler ( 0 , scrollHeight ) ;
247
262
248
263
legend . on ( 'wheel' , null ) ;
249
264
250
265
legend . on ( 'wheel' , function ( ) {
251
266
var e = d3 . event ;
252
267
e . preventDefault ( ) ;
253
- scrollHandler ( e . deltaY / 20 , scrollheight ) ;
268
+ scrollHandler ( e . deltaY / 20 , scrollHeight ) ;
254
269
} ) ;
255
270
256
271
scrollBar . on ( '.drag' , null ) ;
257
272
scrollBox . on ( '.drag' , null ) ;
258
273
var drag = d3 . behavior . drag ( )
259
274
. on ( 'drag' , function ( ) {
260
- scrollHandler ( d3 . event . dy , scrollheight ) ;
275
+ scrollHandler ( d3 . event . dy , scrollHeight ) ;
261
276
} ) ;
262
277
263
278
scrollBar . call ( drag ) ;
@@ -266,12 +281,12 @@ module.exports = function draw(gd) {
266
281
}
267
282
268
283
269
- function scrollHandler ( delta , scrollheight ) {
284
+ function scrollHandler ( delta , scrollHeight ) {
270
285
271
- var scrollBarTrack = scrollheight - constants . scrollBarHeight - 2 * constants . scrollBarMargin ,
286
+ var scrollBarTrack = scrollHeight - constants . scrollBarHeight - 2 * constants . scrollBarMargin ,
272
287
translateY = scrollBox . attr ( 'data-scroll' ) ,
273
- scrollBoxY = Lib . constrain ( translateY - delta , scrollheight - opts . height , 0 ) ,
274
- scrollBarY = - scrollBoxY / ( opts . height - scrollheight ) * scrollBarTrack + constants . scrollBarMargin ;
288
+ scrollBoxY = Lib . constrain ( translateY - delta , scrollHeight - opts . height , 0 ) ,
289
+ scrollBarY = - scrollBoxY / ( opts . height - scrollHeight ) * scrollBarTrack + constants . scrollBarMargin ;
275
290
276
291
scrollBox . attr ( 'data-scroll' , scrollBoxY ) ;
277
292
scrollBox . attr ( 'transform' , 'translate(0, ' + scrollBoxY + ')' ) ;
@@ -454,7 +469,10 @@ function repositionLegend(gd, traces) {
454
469
opts . height = Math . ceil ( opts . height ) ;
455
470
456
471
// lastly check if the margin auto-expand has changed
457
- Plots . autoMargin ( gd , 'legend' , {
472
+ // (using Plots.autoMarginVertical to ensure the requested margins are
473
+ // padded with the layout vertical margins to ensure the legend doesn't
474
+ // exceed the plot area)
475
+ Plots . autoMarginVertical ( gd , 'legend' , {
458
476
x : opts . x ,
459
477
y : opts . y ,
460
478
l : opts . width * ( { right : 1 , center : 0.5 } [ xanchor ] || 0 ) ,
0 commit comments