@@ -71,7 +71,6 @@ legend.supplyLayoutDefaults = function(layoutIn, layoutOut, fullData) {
7171 coerce ( 'borderwidth' ) ;
7272 Lib . coerceFont ( coerce , 'font' , layoutOut . font ) ;
7373
74- coerce ( 'type' ) ;
7574 coerce ( 'traceorder' , defaultOrder ) ;
7675 if ( isGrouped ( layoutOut . legend ) ) coerce ( 'tracegroupgap' ) ;
7776
@@ -462,6 +461,14 @@ legend.draw = function(td) {
462461 . attr ( 'class' , 'scrollbox' ) ;
463462 scrollBox . exit ( ) . remove ( ) ;
464463
464+ var scrollBar = legendsvg . selectAll ( 'rect.scrollbar' )
465+ . data ( [ 0 ] ) ;
466+ scrollBar . enter ( ) . append ( 'rect' )
467+ . attr ( 'class' , 'scrollbar' )
468+ . attr ( 'rx' , 20 )
469+ . attr ( 'ry' , 2 )
470+ . call ( Color . fill , '#808BA4' ) ;
471+
465472 var groups = scrollBox . selectAll ( 'g.groups' )
466473 . data ( legendData ) ;
467474 groups . enter ( ) . append ( 'g' )
@@ -679,22 +686,39 @@ legend.repositionLegend = function(td, traces){
679686 lx = Math . round ( lx ) ;
680687 ly = Math . round ( ly ) ;
681688
682- // Add scroll functionality
689+
683690 var legendsvg = fullLayout . _infolayer . selectAll ( 'svg.legend' ) ,
684691 scrollBox = fullLayout . _infolayer . selectAll ( 'svg.legend .scrollbox' ) ,
685- plotHeight = fullLayout . height - fullLayout . margin . t - fullLayout . margin . b ,
686- scrollheight = Math . min ( plotHeight , legendheight ) ;
692+ scrollBar = fullLayout . _infolayer . selectAll ( 'svg.legend .scrollbar' ) ,
693+ bg = fullLayout . _infolayer . selectAll ( 'svg.legend .bg' ) ;
694+
695+ var plotHeight = fullLayout . height - fullLayout . margin . t - fullLayout . margin . b ,
696+ scrollheight = Math . min ( plotHeight - ly , legendheight ) ,
697+ scrollPosition = scrollBox . attr ( 'viewBox' ) ? scrollBox . attr ( 'viewBox' ) . split ( ' ' ) [ 1 ] : 0 ;
687698
688- scrollBox . attr ( 'viewBox' , '0 0 ' + legendwidth + ' ' + scrollheight ) ;
689699 legendsvg . node ( ) . addEventListener ( 'wheel' , scrollHandler ) ;
700+ legendsvg . call ( Drawing . setRect , lx , ly , legendwidth , scrollheight ) ;
701+
702+ bg . style ( { width : legendwidth , height : scrollheight } ) ;
703+
704+ scrollBox . attr ( 'viewBox' , '0 ' + scrollPosition + ' ' + legendwidth + ' ' + scrollheight ) ;
705+
706+ if ( td . firstRender ) scrollBar . call ( Drawing . setRect , legendwidth - 6 , 10 , 4 , 20 ) ;
690707
691708 function scrollHandler ( e ) {
692709 e . preventDefault ( ) ;
693710
694- var scroll = scrollBox . attr ( 'viewBox' ) . split ( ' ' ) ;
695- scroll [ 1 ] = constrain ( 0 , Math . max ( legendheight - scrollheight , 0 ) , + scroll [ 1 ] + e . deltaY ) ;
711+ // Scale movement to simulate native scroll performance
712+ var scrollDiff = e . deltaY / 25 ,
713+ viewBox = scrollBox . attr ( 'viewBox' ) . split ( ' ' ) ;
714+
715+ var scrollBoxY = constrain ( 0 , Math . max ( legendheight - scrollheight , 0 ) , + viewBox [ 1 ] + scrollDiff ) ,
716+ scrollBarY = scrollBoxY / legendheight * ( scrollheight ) + 10 ;
696717
697- scrollBox . attr ( 'viewBox' , scroll . join ( ' ' ) ) ;
718+ viewBox [ 1 ] = scrollBoxY ;
719+
720+ scrollBox . attr ( 'viewBox' , viewBox . join ( ' ' ) ) ;
721+ scrollBar . call ( Drawing . setRect , legendwidth - 6 , scrollBarY , 4 , 20 ) ;
698722 }
699723
700724 function constrain ( min , max , c ) {
@@ -707,11 +731,6 @@ legend.repositionLegend = function(td, traces){
707731 }
708732 }
709733
710- fullLayout . _infolayer . selectAll ( 'svg.legend' )
711- . call ( Drawing . setRect , lx , ly , legendwidth , scrollheight ) ;
712- fullLayout . _infolayer . selectAll ( 'svg.legend .bg' )
713- . style ( { width : legendwidth , height : scrollheight } ) ;
714-
715734 // lastly check if the margin auto-expand has changed
716735 Plots . autoMargin ( td , 'legend' , {
717736 x : opts . x ,
0 commit comments