1111
1212var d3 = require ( 'd3' ) ;
1313var isNumeric = require ( 'fast-isnumeric' ) ;
14+ var tinycolor = require ( 'tinycolor2' ) ;
1415
1516var Registry = require ( '../../registry' ) ;
1617var Color = require ( '../color' ) ;
@@ -202,7 +203,7 @@ drawing.symbolNumber = function(v) {
202203 return Math . floor ( Math . max ( v , 0 ) ) ;
203204} ;
204205
205- function singlePointStyle ( d , sel , trace , markerScale , lineScale , marker , markerLine ) {
206+ function singlePointStyle ( d , sel , trace , markerScale , lineScale , marker , markerLine , gd ) {
206207 // only scatter & box plots get marker path and opacity
207208 // bars, histograms don't
208209 if ( Registry . traceIs ( trace , 'symbols' ) ) {
@@ -237,6 +238,8 @@ function singlePointStyle(d, sel, trace, markerScale, lineScale, marker, markerL
237238 } ) ;
238239 }
239240
241+ var perPointGradient = false ;
242+
240243 // 'so' is suspected outliers, for box plots
241244 var fillColor ,
242245 lineColor ,
@@ -256,8 +259,12 @@ function singlePointStyle(d, sel, trace, markerScale, lineScale, marker, markerL
256259 else if ( Array . isArray ( markerLine . color ) ) lineColor = Color . defaultLine ;
257260 else lineColor = markerLine . color ;
258261
262+ if ( Array . isArray ( marker . color ) ) {
263+ fillColor = Color . defaultLine ;
264+ perPointGradient = true ;
265+ }
266+
259267 if ( 'mc' in d ) fillColor = d . mcc = markerScale ( d . mc ) ;
260- else if ( Array . isArray ( marker . color ) ) fillColor = Color . defaultLine ;
261268 else fillColor = marker . color || 'rgba(0,0,0,0)' ;
262269 }
263270
@@ -271,24 +278,93 @@ function singlePointStyle(d, sel, trace, markerScale, lineScale, marker, markerL
271278 } ) ;
272279 }
273280 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+
276303 if ( lineWidth ) {
277304 sel . call ( Color . stroke , lineColor ) ;
278305 }
279306 }
280307}
281308
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 } ;
285311
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 ;
290366
291- singlePointStyle ( d , sel , trace , markerScale , lineScale , marker , markerLine ) ;
367+ singlePointStyle ( d , sel , trace , markerScale , lineScale , marker , marker . line , gd ) ;
292368
293369} ;
294370
@@ -298,11 +374,12 @@ drawing.pointStyle = function(s, trace) {
298374 // allow array marker and marker line colors to be
299375 // scaled by given max and min to colorscales
300376 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 ( ) ) ;
303380
304381 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 ) ;
306383 } ) ;
307384} ;
308385
0 commit comments