@@ -39,9 +39,9 @@ module.exports = function draw(gd, id) {
3939 // opts: options object, containing everything from attributes
4040 // plus a few others that are the equivalent of the colorbar "data"
4141 var opts = { } ;
42- Object . keys ( attributes ) . forEach ( function ( k ) {
42+ for ( var k in attributes ) {
4343 opts [ k ] = null ;
44- } ) ;
44+ }
4545 // fillcolor can be a d3 scale, domain is z values, range is colors
4646 // or leave it out for no fill,
4747 // or set to a string constant for single-color fill
@@ -57,17 +57,23 @@ module.exports = function draw(gd, id) {
5757 // contour map) if this is omitted, fillcolors will be
5858 // evaluated halfway between levels
5959 opts . filllevels = null ;
60+ // for continuous colorscales: fill with a gradient instead of explicit levels
61+ // value should be the colorscale [[0, c0], [v1, c1], ..., [1, cEnd]]
62+ opts . fillgradient = null ;
63+ // when using a gradient, we need the data range specified separately
64+ opts . zrange = null ;
6065
6166 function component ( ) {
6267 var fullLayout = gd . _fullLayout ,
6368 gs = fullLayout . _size ;
6469 if ( ( typeof opts . fillcolor !== 'function' ) &&
65- ( typeof opts . line . color !== 'function' ) ) {
70+ ( typeof opts . line . color !== 'function' ) &&
71+ ! opts . fillgradient ) {
6672 fullLayout . _infolayer . selectAll ( 'g.' + id ) . remove ( ) ;
6773 return ;
6874 }
69- var zrange = d3 . extent ( ( ( typeof opts . fillcolor === 'function' ) ?
70- opts . fillcolor : opts . line . color ) . domain ( ) ) ;
75+ var zrange = opts . zrange || ( d3 . extent ( ( ( typeof opts . fillcolor === 'function' ) ?
76+ opts . fillcolor : opts . line . color ) . domain ( ) ) ) ;
7177 var linelevels = [ ] ;
7278 var filllevels = [ ] ;
7379 var linecolormap = typeof opts . line . color === 'function' ?
@@ -87,7 +93,10 @@ module.exports = function draw(gd, id) {
8793 if ( l > zr0 && l < zr1 ) linelevels . push ( l ) ;
8894 }
8995
90- if ( typeof opts . fillcolor === 'function' ) {
96+ if ( opts . fillgradient ) {
97+ filllevels = [ 0 ] ;
98+ }
99+ else if ( typeof opts . fillcolor === 'function' ) {
91100 if ( opts . filllevels ) {
92101 l0 = opts . filllevels . end + opts . filllevels . size / 100 ;
93102 ls = opts . filllevels . size ;
@@ -358,6 +367,12 @@ module.exports = function draw(gd, id) {
358367 . classed ( cn . cbfill , true )
359368 . style ( 'stroke' , 'none' ) ;
360369 fills . exit ( ) . remove ( ) ;
370+
371+ var zBounds = zrange
372+ . map ( cbAxisOut . c2p )
373+ . map ( Math . round )
374+ . sort ( function ( a , b ) { return a - b ; } ) ;
375+
361376 fills . each ( function ( d , i ) {
362377 var z = [
363378 ( i === 0 ) ? zrange [ 0 ] :
@@ -370,25 +385,27 @@ module.exports = function draw(gd, id) {
370385
371386 // offset the side adjoining the next rectangle so they
372387 // overlap, to prevent antialiasing gaps
373- if ( i !== filllevels . length - 1 ) {
374- z [ 1 ] += ( z [ 1 ] > z [ 0 ] ) ? 1 : - 1 ;
375- }
376-
377-
378- // Tinycolor can't handle exponents and
379- // at this scale, removing it makes no difference.
380- var colorString = fillcolormap ( d ) . replace ( 'e-' , '' ) ,
381- opaqueColor = tinycolor ( colorString ) . toHexString ( ) ;
388+ z [ 1 ] = Lib . constrain ( z [ 1 ] + ( z [ 1 ] > z [ 0 ] ) ? 1 : - 1 , zBounds [ 0 ] , zBounds [ 1 ] ) ;
382389
383390 // Colorbar cannot currently support opacities so we
384391 // use an opaque fill even when alpha channels present
385- d3 . select ( this ) . attr ( {
392+ var fillEl = d3 . select ( this ) . attr ( {
386393 x : xLeft ,
387394 width : Math . max ( thickPx , 2 ) ,
388395 y : d3 . min ( z ) ,
389396 height : Math . max ( d3 . max ( z ) - d3 . min ( z ) , 2 ) ,
390- fill : opaqueColor
391397 } ) ;
398+
399+ if ( opts . fillgradient ) {
400+ Drawing . gradient ( fillEl , gd , id , 'vertical' ,
401+ opts . fillgradient , 'fill' ) ;
402+ }
403+ else {
404+ // Tinycolor can't handle exponents and
405+ // at this scale, removing it makes no difference.
406+ var colorString = fillcolormap ( d ) . replace ( 'e-' , '' ) ;
407+ fillEl . attr ( 'fill' , tinycolor ( colorString ) . toHexString ( ) ) ;
408+ }
392409 } ) ;
393410
394411 var lines = container . select ( '.cblines' )
@@ -650,13 +667,13 @@ module.exports = function draw(gd, id) {
650667
651668 // or use .options to set multiple options at once via a dictionary
652669 component . options = function ( o ) {
653- Object . keys ( o ) . forEach ( function ( name ) {
670+ for ( var name in o ) {
654671 // in case something random comes through
655672 // that's not an option, ignore it
656673 if ( typeof component [ name ] === 'function' ) {
657674 component [ name ] ( o [ name ] ) ;
658675 }
659- } ) ;
676+ }
660677 return component ;
661678 } ;
662679
0 commit comments