11
11
12
12
var d3 = require ( 'd3' ) ;
13
13
var isNumeric = require ( 'fast-isnumeric' ) ;
14
+ var tinycolor = require ( 'tinycolor2' ) ;
14
15
15
16
var Registry = require ( '../../registry' ) ;
16
17
var Color = require ( '../color' ) ;
@@ -202,7 +203,7 @@ drawing.symbolNumber = function(v) {
202
203
return Math . floor ( Math . max ( v , 0 ) ) ;
203
204
} ;
204
205
205
- function singlePointStyle ( d , sel , trace , markerScale , lineScale , marker , markerLine ) {
206
+ function singlePointStyle ( d , sel , trace , markerScale , lineScale , marker , markerLine , gd ) {
206
207
// only scatter & box plots get marker path and opacity
207
208
// bars, histograms don't
208
209
if ( Registry . traceIs ( trace , 'symbols' ) ) {
@@ -237,6 +238,8 @@ function singlePointStyle(d, sel, trace, markerScale, lineScale, marker, markerL
237
238
} ) ;
238
239
}
239
240
241
+ var perPointGradient = false ;
242
+
240
243
// 'so' is suspected outliers, for box plots
241
244
var fillColor ,
242
245
lineColor ,
@@ -256,8 +259,12 @@ function singlePointStyle(d, sel, trace, markerScale, lineScale, marker, markerL
256
259
else if ( Array . isArray ( markerLine . color ) ) lineColor = Color . defaultLine ;
257
260
else lineColor = markerLine . color ;
258
261
262
+ if ( Array . isArray ( marker . color ) ) {
263
+ fillColor = Color . defaultLine ;
264
+ perPointGradient = true ;
265
+ }
266
+
259
267
if ( 'mc' in d ) fillColor = d . mcc = markerScale ( d . mc ) ;
260
- else if ( Array . isArray ( marker . color ) ) fillColor = Color . defaultLine ;
261
268
else fillColor = marker . color || 'rgba(0,0,0,0)' ;
262
269
}
263
270
@@ -271,24 +278,93 @@ function singlePointStyle(d, sel, trace, markerScale, lineScale, marker, markerL
271
278
} ) ;
272
279
}
273
280
else {
274
- sel . style ( 'stroke-width' , lineWidth + 'px' )
275
- . call ( Color . fill , fillColor ) ;
281
+ sel . style ( 'stroke-width' , lineWidth + 'px' ) ;
282
+
283
+ var markerGradient = marker . gradient ;
284
+
285
+ var gradientType = d . mgt ;
286
+ if ( gradientType ) perPointGradient = true ;
287
+ else gradientType = markerGradient && markerGradient . type ;
288
+
289
+ if ( gradientType && gradientType !== 'none' ) {
290
+ var gradientColor = d . mgc ;
291
+ if ( gradientColor ) perPointGradient = true ;
292
+ else gradientColor = markerGradient . color ;
293
+
294
+ var gradientID = 'g' + gd . _fullLayout . _uid + '-' + trace . uid ;
295
+ if ( perPointGradient ) gradientID += '-' + d . i ;
296
+
297
+ sel . call ( drawing . gradient , gd , gradientID , gradientType , fillColor , gradientColor ) ;
298
+ }
299
+ else {
300
+ sel . call ( Color . fill , fillColor ) ;
301
+ }
302
+
276
303
if ( lineWidth ) {
277
304
sel . call ( Color . stroke , lineColor ) ;
278
305
}
279
306
}
280
307
}
281
308
282
- drawing . singlePointStyle = function ( d , sel , trace ) {
283
- var marker = trace . marker ,
284
- markerLine = marker . line ;
309
+ var HORZGRADIENT = { x1 : 1 , x2 : 0 , y1 : 0 , y2 : 0 } ;
310
+ var VERTGRADIENT = { x1 : 0 , x2 : 0 , y1 : 1 , y2 : 0 } ;
285
311
286
- // allow array marker and marker line colors to be
287
- // scaled by given max and min to colorscales
288
- var markerScale = drawing . tryColorscale ( marker , '' ) ,
289
- lineScale = drawing . tryColorscale ( marker , 'line' ) ;
312
+ drawing . gradient = function ( sel , gd , gradientID , type , color1 , color2 ) {
313
+ var gradient = gd . _fullLayout . _defs . select ( '.gradients' )
314
+ . selectAll ( '#' + gradientID )
315
+ . data ( [ type + color1 + color2 ] , Lib . identity ) ;
316
+
317
+ gradient . exit ( ) . remove ( ) ;
318
+
319
+ gradient . enter ( )
320
+ . append ( type === 'radial' ? 'radialGradient' : 'linearGradient' )
321
+ . each ( function ( ) {
322
+ var el = d3 . select ( this ) ;
323
+ if ( type === 'horizontal' ) el . attr ( HORZGRADIENT ) ;
324
+ else if ( type === 'vertical' ) el . attr ( VERTGRADIENT ) ;
325
+
326
+ el . attr ( 'id' , gradientID ) ;
327
+
328
+ var tc1 = tinycolor ( color1 ) ;
329
+ var tc2 = tinycolor ( color2 ) ;
330
+
331
+ el . append ( 'stop' ) . attr ( {
332
+ offset : '0%' ,
333
+ 'stop-color' : Color . tinyRGB ( tc2 ) ,
334
+ 'stop-opacity' : tc2 . getAlpha ( )
335
+ } ) ;
336
+
337
+ el . append ( 'stop' ) . attr ( {
338
+ offset : '100%' ,
339
+ 'stop-color' : Color . tinyRGB ( tc1 ) ,
340
+ 'stop-opacity' : tc1 . getAlpha ( )
341
+ } ) ;
342
+ } ) ;
343
+
344
+ sel . style ( {
345
+ fill : 'url(#' + gradientID + ')' ,
346
+ 'fill-opacity' : null
347
+ } ) ;
348
+ } ;
349
+
350
+ /*
351
+ * Make the gradients container and clear out any previous gradients.
352
+ * We never collect all the gradients we need in one place,
353
+ * so we can't ever remove gradients that have stopped being useful,
354
+ * except all at once before a full redraw.
355
+ * The upside of this is arbitrary points can share gradient defs
356
+ */
357
+ drawing . initGradients = function ( gd ) {
358
+ var gradientsGroup = gd . _fullLayout . _defs . selectAll ( '.gradients' ) . data ( [ 0 ] ) ;
359
+ gradientsGroup . enter ( ) . append ( 'g' ) . classed ( 'gradients' , true ) ;
360
+
361
+ gradientsGroup . selectAll ( 'linearGradient,radialGradient' ) . remove ( ) ;
362
+ } ;
363
+
364
+ drawing . singlePointStyle = function ( d , sel , trace , markerScale , lineScale , gd ) {
365
+ var marker = trace . marker ;
290
366
291
- singlePointStyle ( d , sel , trace , markerScale , lineScale , marker , markerLine ) ;
367
+ singlePointStyle ( d , sel , trace , markerScale , lineScale , marker , marker . line , gd ) ;
292
368
293
369
} ;
294
370
@@ -298,11 +374,12 @@ drawing.pointStyle = function(s, trace) {
298
374
// allow array marker and marker line colors to be
299
375
// scaled by given max and min to colorscales
300
376
var marker = trace . marker ;
301
- var markerScale = drawing . tryColorscale ( marker , '' ) ,
302
- lineScale = drawing . tryColorscale ( marker , 'line' ) ;
377
+ var markerScale = drawing . tryColorscale ( marker , '' ) ;
378
+ var lineScale = drawing . tryColorscale ( marker , 'line' ) ;
379
+ var gd = Lib . getPlotDiv ( s . node ( ) ) ;
303
380
304
381
s . each ( function ( d ) {
305
- drawing . singlePointStyle ( d , d3 . select ( this ) , trace , markerScale , lineScale ) ;
382
+ drawing . singlePointStyle ( d , d3 . select ( this ) , trace , markerScale , lineScale , gd ) ;
306
383
} ) ;
307
384
} ;
308
385
0 commit comments