@@ -364,67 +364,129 @@ drawing.gradient = function(sel, gd, gradientID, type, colorscale, prop) {
364364 * for this pattern, so that we don't create unnecessary definitions
365365 * @param {string } bgcolor: background color for this pattern
366366 * @param {string } fgcolor: foreground color for this pattern
367- * @param {number } scale: scale of this pattern
367+ * @param {number } size: size of unit squares for repetition of this pattern
368368 * @param {number } solidity: how solid lines of this pattern are
369369 * @param {string } prop: the property to apply to, 'fill' or 'stroke'
370370 */
371- drawing . pattern = function ( sel , gd , patternID , shape , bgcolor , fgcolor , scale , solidity , prop ) {
371+ drawing . pattern = function ( sel , gd , patternID , shape , bgcolor , fgcolor , size , solidity , prop ) {
372372 var fullLayout = gd . _fullLayout ;
373373 var fullID = 'p' + fullLayout . _uid + '-' + patternID ;
374- var baseSize = 8 * scale ;
375374 var width , height ;
376375
377- var path = '' ;
376+ var path , linewidth , radius ;
377+ var patternTag ;
378+ var patternAttrs = { } ;
378379 switch ( shape ) {
379380 case '/' :
380- width = baseSize * Math . sqrt ( 2 ) ;
381- height = baseSize * Math . sqrt ( 2 ) ;
382- path = 'M-1,1l2,-2' +
381+ width = size * Math . sqrt ( 2 ) ;
382+ height = size * Math . sqrt ( 2 ) ;
383+ path = 'M-' + ( width / 4 ) + ',' + ( height / 4 ) + 'l' + ( width / 2 ) + ',-' + ( height / 2 ) +
383384 'M0,' + height + 'L' + width + ',0' +
384- 'M' + ( width - 1 ) + ',' + ( height + 1 ) + 'l2,-2' ;
385+ 'M' + ( width / 4 * 3 ) + ',' + ( height / 4 * 5 ) + 'l' + ( width / 2 ) + ',-' + ( height / 2 ) ;
386+ linewidth = solidity * size ;
387+ patternTag = 'path' ;
388+ patternAttrs = {
389+ 'd' : path ,
390+ 'stroke' : fgcolor ,
391+ 'stroke-width' : linewidth + 'px'
392+ } ;
385393 break ;
386394 case '\\' :
387- width = baseSize * Math . sqrt ( 2 ) ;
388- height = baseSize * Math . sqrt ( 2 ) ;
389- path = 'M' + ( width - 1 ) + ',-1l2,2' +
395+ width = size * Math . sqrt ( 2 ) ;
396+ height = size * Math . sqrt ( 2 ) ;
397+ path = 'M' + ( width / 4 * 3 ) + ',-' + ( height / 4 ) + 'l' + ( width / 2 ) + ',' + ( height / 2 ) +
390398 'M0,0L' + width + ',' + height +
391- 'M-1,' + ( height - 1 ) + 'l2,2' ;
399+ 'M-' + ( width / 4 ) + ',' + ( height / 4 * 3 ) + 'l' + ( width / 2 ) + ',' + ( height / 2 ) ;
400+ linewidth = solidity * size ;
401+ patternTag = 'path' ;
402+ patternAttrs = {
403+ 'd' : path ,
404+ 'stroke' : fgcolor ,
405+ 'stroke-width' : linewidth + 'px'
406+ } ;
392407 break ;
393408 case 'x' :
394- width = baseSize * Math . sqrt ( 2 ) ;
395- height = baseSize * Math . sqrt ( 2 ) ;
396- path = 'M-1,1l2,-2' +
409+ width = size * Math . sqrt ( 2 ) ;
410+ height = size * Math . sqrt ( 2 ) ;
411+ path = 'M-' + ( width / 4 ) + ',' + ( height / 4 ) + 'l' + ( width / 2 ) + ',-' + ( height / 2 ) +
397412 'M0,' + height + 'L' + width + ',0' +
398- 'M' + ( width - 1 ) + ',' + ( height + 1 ) + 'l2,-2' +
399- 'M' + ( width - 1 ) + ',-1l2,2' +
413+ 'M' + ( width / 4 * 3 ) + ',' + ( height / 4 * 5 ) + 'l' + ( width / 2 ) + ',-' + ( height / 2 ) +
414+ 'M' + ( width / 4 * 3 ) + ',-' + ( height / 4 ) + 'l' + ( width / 2 ) + ',' + ( height / 2 ) +
400415 'M0,0L' + width + ',' + height +
401- 'M-1,' + ( height - 1 ) + 'l2,2' ;
416+ 'M-' + ( width / 4 ) + ',' + ( height / 4 * 3 ) + 'l' + ( width / 2 ) + ',' + ( height / 2 ) ;
417+ linewidth = size - size * Math . sqrt ( 1.0 - solidity ) ;
418+ patternTag = 'path' ;
419+ patternAttrs = {
420+ 'd' : path ,
421+ 'stroke' : fgcolor ,
422+ 'stroke-width' : linewidth + 'px'
423+ } ;
402424 break ;
403425 case '|' :
404- width = baseSize ;
405- height = baseSize ;
426+ width = size ;
427+ height = size ;
428+ patternTag = 'path' ;
406429 path = 'M' + ( width / 2 ) + ',0L' + ( width / 2 ) + ',' + height ;
430+ linewidth = solidity * size ;
431+ patternTag = 'path' ;
432+ patternAttrs = {
433+ 'd' : path ,
434+ 'stroke' : fgcolor ,
435+ 'stroke-width' : linewidth + 'px'
436+ } ;
407437 break ;
408438 case '-' :
409- width = baseSize ;
410- height = baseSize ;
439+ width = size ;
440+ height = size ;
441+ patternTag = 'path' ;
411442 path = 'M0,' + ( height / 2 ) + 'L' + width + ',' + ( height / 2 ) ;
443+ linewidth = solidity * size ;
444+ patternTag = 'path' ;
445+ patternAttrs = {
446+ 'd' : path ,
447+ 'stroke' : fgcolor ,
448+ 'stroke-width' : linewidth + 'px'
449+ } ;
412450 break ;
413451 case '+' :
414- width = baseSize ;
415- height = baseSize ;
452+ width = size ;
453+ height = size ;
454+ patternTag = 'path' ;
416455 path = 'M' + ( width / 2 ) + ',0L' + ( width / 2 ) + ',' + height +
417456 'M0,' + ( height / 2 ) + 'L' + width + ',' + ( height / 2 ) ;
457+ linewidth = size - size * Math . sqrt ( 1.0 - solidity ) ;
458+ patternTag = 'path' ;
459+ patternAttrs = {
460+ 'd' : path ,
461+ 'stroke' : fgcolor ,
462+ 'stroke-width' : linewidth + 'px'
463+ } ;
418464 break ;
419465 case '.' :
420- width = baseSize ;
421- height = baseSize ;
466+ width = size ;
467+ height = size ;
468+ if ( solidity < Math . PI / 4 ) {
469+ radius = Math . sqrt ( solidity * size * size / Math . PI ) ;
470+ } else {
471+ // linear interpolation
472+ var linearFn = function ( x , x0 , x1 , y0 , y1 ) {
473+ return y0 + ( y1 - y0 ) * ( x - x0 ) / ( x1 - x0 ) ;
474+ } ;
475+ radius = linearFn ( solidity , Math . PI / 4 , 1.0 , size / 2 , size / Math . sqrt ( 2 ) ) ;
476+ }
477+ patternTag = 'circle' ;
478+ patternAttrs = {
479+ 'cx' : width / 2 ,
480+ 'cy' : height / 2 ,
481+ 'r' : radius ,
482+ 'fill' : fgcolor
483+ } ;
422484 break ;
423485 }
424486
425487 var pattern = fullLayout . _defs . select ( '.patterns' )
426488 . selectAll ( '#' + fullID )
427- . data ( [ 0 ] ) ;
489+ . data ( [ shape + ';' + bgcolor + ';' + fgcolor + ';' + size + ';' + solidity ] ) ;
428490
429491 pattern . exit ( ) . remove ( ) ;
430492
@@ -440,9 +502,9 @@ drawing.pattern = function(sel, gd, patternID, shape, bgcolor, fgcolor, scale, s
440502 'patternUnits' : 'userSpaceOnUse'
441503 } ) ;
442504
443- var rects = el . selectAll ( 'rect' ) . data ( [ 0 ] ) ;
444- rects . exit ( ) . remove ( ) ;
445505 if ( bgcolor ) {
506+ var rects = el . selectAll ( 'rect' ) . data ( [ 0 ] ) ;
507+ rects . exit ( ) . remove ( ) ;
446508 rects . enter ( )
447509 . append ( 'rect' )
448510 . attr ( {
@@ -452,28 +514,11 @@ drawing.pattern = function(sel, gd, patternID, shape, bgcolor, fgcolor, scale, s
452514 } ) ;
453515 }
454516
455- if ( shape === '.' ) {
456- var circles = el . selectAll ( 'circle' ) . data ( [ 0 ] ) ;
457- circles . exit ( ) . remove ( ) ;
458- circles . enter ( )
459- . append ( 'circle' )
460- . attr ( {
461- 'cx' : width / 2 ,
462- 'cy' : height / 2 ,
463- 'r' : solidity ,
464- 'fill' : fgcolor
465- } ) ;
466- } else {
467- var paths = el . selectAll ( 'path' ) . data ( [ 0 ] ) ;
468- paths . exit ( ) . remove ( ) ;
469- paths . enter ( )
470- . append ( 'path' )
471- . attr ( {
472- 'd' : path ,
473- 'stroke' : fgcolor ,
474- 'stroke-width' : solidity + 'px'
475- } ) ;
476- }
517+ var patterns = el . selectAll ( patternTag ) . data ( [ 0 ] ) ;
518+ patterns . exit ( ) . remove ( ) ;
519+ patterns . enter ( )
520+ . append ( patternTag )
521+ . attr ( patternAttrs ) ;
477522 } ) ;
478523
479524 sel . style ( prop , getFullUrl ( fullID , gd ) )
@@ -632,7 +677,7 @@ drawing.singlePointStyle = function(d, sel, trace, fns, gd) {
632677 }
633678 return mp ;
634679 } ;
635- var markerPattern = marker . patternfill ;
680+ var markerPattern = marker . pattern ;
636681 var patternShape = markerPattern && getPatternAttr ( markerPattern . shape , d . i , '' ) ;
637682
638683 if ( gradientType && gradientType !== 'none' ) {
@@ -647,18 +692,18 @@ drawing.singlePointStyle = function(d, sel, trace, fns, gd) {
647692 [ [ 0 , gradientColor ] , [ 1 , fillColor ] ] , 'fill' ) ;
648693 } else if ( patternShape ) {
649694 var patternBGColor = getPatternAttr ( markerPattern . bgcolor , d . i , null ) ;
650- var patternScale = getPatternAttr ( markerPattern . scale , d . i , 1 ) ;
695+ var patternSize = getPatternAttr ( markerPattern . size , d . i , 1 ) ;
651696 var patternSolidity = getPatternAttr ( markerPattern . solidity , d . i , 1 ) ;
652697 var perPointPattern = Array . isArray ( markerPattern . shape ) ||
653698 Array . isArray ( markerPattern . bgcolor ) ||
654- Array . isArray ( markerPattern . scale ) ||
699+ Array . isArray ( markerPattern . size ) ||
655700 Array . isArray ( markerPattern . solidity ) ;
656701
657702 var patternID = trace . uid ;
658703 if ( perPointPattern ) patternID += '-' + d . i ;
659704
660705 drawing . pattern ( sel , gd , patternID , patternShape , patternBGColor , fillColor ,
661- patternScale , patternSolidity , 'fill' ) ;
706+ patternSize , patternSolidity , 'fill' ) ;
662707 } else {
663708 Color . fill ( sel , fillColor ) ;
664709 }
0 commit comments