@@ -39,9 +39,9 @@ module.exports = function draw(gd, id) {
39
39
// opts: options object, containing everything from attributes
40
40
// plus a few others that are the equivalent of the colorbar "data"
41
41
var opts = { } ;
42
- Object . keys ( attributes ) . forEach ( function ( k ) {
42
+ for ( var k in attributes ) {
43
43
opts [ k ] = null ;
44
- } ) ;
44
+ }
45
45
// fillcolor can be a d3 scale, domain is z values, range is colors
46
46
// or leave it out for no fill,
47
47
// or set to a string constant for single-color fill
@@ -57,17 +57,23 @@ module.exports = function draw(gd, id) {
57
57
// contour map) if this is omitted, fillcolors will be
58
58
// evaluated halfway between levels
59
59
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 ;
60
65
61
66
function component ( ) {
62
67
var fullLayout = gd . _fullLayout ,
63
68
gs = fullLayout . _size ;
64
69
if ( ( typeof opts . fillcolor !== 'function' ) &&
65
- ( typeof opts . line . color !== 'function' ) ) {
70
+ ( typeof opts . line . color !== 'function' ) &&
71
+ ! opts . fillgradient ) {
66
72
fullLayout . _infolayer . selectAll ( 'g.' + id ) . remove ( ) ;
67
73
return ;
68
74
}
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 ( ) ) ) ;
71
77
var linelevels = [ ] ;
72
78
var filllevels = [ ] ;
73
79
var linecolormap = typeof opts . line . color === 'function' ?
@@ -87,7 +93,10 @@ module.exports = function draw(gd, id) {
87
93
if ( l > zr0 && l < zr1 ) linelevels . push ( l ) ;
88
94
}
89
95
90
- if ( typeof opts . fillcolor === 'function' ) {
96
+ if ( opts . fillgradient ) {
97
+ filllevels = [ 0 ] ;
98
+ }
99
+ else if ( typeof opts . fillcolor === 'function' ) {
91
100
if ( opts . filllevels ) {
92
101
l0 = opts . filllevels . end + opts . filllevels . size / 100 ;
93
102
ls = opts . filllevels . size ;
@@ -358,6 +367,12 @@ module.exports = function draw(gd, id) {
358
367
. classed ( cn . cbfill , true )
359
368
. style ( 'stroke' , 'none' ) ;
360
369
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
+
361
376
fills . each ( function ( d , i ) {
362
377
var z = [
363
378
( i === 0 ) ? zrange [ 0 ] :
@@ -370,25 +385,27 @@ module.exports = function draw(gd, id) {
370
385
371
386
// offset the side adjoining the next rectangle so they
372
387
// 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 ] ) ;
382
389
383
390
// Colorbar cannot currently support opacities so we
384
391
// use an opaque fill even when alpha channels present
385
- d3 . select ( this ) . attr ( {
392
+ var fillEl = d3 . select ( this ) . attr ( {
386
393
x : xLeft ,
387
394
width : Math . max ( thickPx , 2 ) ,
388
395
y : d3 . min ( z ) ,
389
396
height : Math . max ( d3 . max ( z ) - d3 . min ( z ) , 2 ) ,
390
- fill : opaqueColor
391
397
} ) ;
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
+ }
392
409
} ) ;
393
410
394
411
var lines = container . select ( '.cblines' )
@@ -650,13 +667,13 @@ module.exports = function draw(gd, id) {
650
667
651
668
// or use .options to set multiple options at once via a dictionary
652
669
component . options = function ( o ) {
653
- Object . keys ( o ) . forEach ( function ( name ) {
670
+ for ( var name in o ) {
654
671
// in case something random comes through
655
672
// that's not an option, ignore it
656
673
if ( typeof component [ name ] === 'function' ) {
657
674
component [ name ] ( o [ name ] ) ;
658
675
}
659
- } ) ;
676
+ }
660
677
return component ;
661
678
} ;
662
679
0 commit comments