@@ -364,67 +364,129 @@ drawing.gradient = function(sel, gd, gradientID, type, colorscale, prop) {
364
364
* for this pattern, so that we don't create unnecessary definitions
365
365
* @param {string } bgcolor: background color for this pattern
366
366
* @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
368
368
* @param {number } solidity: how solid lines of this pattern are
369
369
* @param {string } prop: the property to apply to, 'fill' or 'stroke'
370
370
*/
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 ) {
372
372
var fullLayout = gd . _fullLayout ;
373
373
var fullID = 'p' + fullLayout . _uid + '-' + patternID ;
374
- var baseSize = 8 * scale ;
375
374
var width , height ;
376
375
377
- var path = '' ;
376
+ var path , linewidth , radius ;
377
+ var patternTag ;
378
+ var patternAttrs = { } ;
378
379
switch ( shape ) {
379
380
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 ) +
383
384
'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
+ } ;
385
393
break ;
386
394
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 ) +
390
398
'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
+ } ;
392
407
break ;
393
408
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 ) +
397
412
'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 ) +
400
415
'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
+ } ;
402
424
break ;
403
425
case '|' :
404
- width = baseSize ;
405
- height = baseSize ;
426
+ width = size ;
427
+ height = size ;
428
+ patternTag = 'path' ;
406
429
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
+ } ;
407
437
break ;
408
438
case '-' :
409
- width = baseSize ;
410
- height = baseSize ;
439
+ width = size ;
440
+ height = size ;
441
+ patternTag = 'path' ;
411
442
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
+ } ;
412
450
break ;
413
451
case '+' :
414
- width = baseSize ;
415
- height = baseSize ;
452
+ width = size ;
453
+ height = size ;
454
+ patternTag = 'path' ;
416
455
path = 'M' + ( width / 2 ) + ',0L' + ( width / 2 ) + ',' + height +
417
456
'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
+ } ;
418
464
break ;
419
465
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
+ } ;
422
484
break ;
423
485
}
424
486
425
487
var pattern = fullLayout . _defs . select ( '.patterns' )
426
488
. selectAll ( '#' + fullID )
427
- . data ( [ 0 ] ) ;
489
+ . data ( [ shape + ';' + bgcolor + ';' + fgcolor + ';' + size + ';' + solidity ] ) ;
428
490
429
491
pattern . exit ( ) . remove ( ) ;
430
492
@@ -440,9 +502,9 @@ drawing.pattern = function(sel, gd, patternID, shape, bgcolor, fgcolor, scale, s
440
502
'patternUnits' : 'userSpaceOnUse'
441
503
} ) ;
442
504
443
- var rects = el . selectAll ( 'rect' ) . data ( [ 0 ] ) ;
444
- rects . exit ( ) . remove ( ) ;
445
505
if ( bgcolor ) {
506
+ var rects = el . selectAll ( 'rect' ) . data ( [ 0 ] ) ;
507
+ rects . exit ( ) . remove ( ) ;
446
508
rects . enter ( )
447
509
. append ( 'rect' )
448
510
. attr ( {
@@ -452,28 +514,11 @@ drawing.pattern = function(sel, gd, patternID, shape, bgcolor, fgcolor, scale, s
452
514
} ) ;
453
515
}
454
516
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 ) ;
477
522
} ) ;
478
523
479
524
sel . style ( prop , getFullUrl ( fullID , gd ) )
@@ -632,7 +677,7 @@ drawing.singlePointStyle = function(d, sel, trace, fns, gd) {
632
677
}
633
678
return mp ;
634
679
} ;
635
- var markerPattern = marker . patternfill ;
680
+ var markerPattern = marker . pattern ;
636
681
var patternShape = markerPattern && getPatternAttr ( markerPattern . shape , d . i , '' ) ;
637
682
638
683
if ( gradientType && gradientType !== 'none' ) {
@@ -647,18 +692,18 @@ drawing.singlePointStyle = function(d, sel, trace, fns, gd) {
647
692
[ [ 0 , gradientColor ] , [ 1 , fillColor ] ] , 'fill' ) ;
648
693
} else if ( patternShape ) {
649
694
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 ) ;
651
696
var patternSolidity = getPatternAttr ( markerPattern . solidity , d . i , 1 ) ;
652
697
var perPointPattern = Array . isArray ( markerPattern . shape ) ||
653
698
Array . isArray ( markerPattern . bgcolor ) ||
654
- Array . isArray ( markerPattern . scale ) ||
699
+ Array . isArray ( markerPattern . size ) ||
655
700
Array . isArray ( markerPattern . solidity ) ;
656
701
657
702
var patternID = trace . uid ;
658
703
if ( perPointPattern ) patternID += '-' + d . i ;
659
704
660
705
drawing . pattern ( sel , gd , patternID , patternShape , patternBGColor , fillColor ,
661
- patternScale , patternSolidity , 'fill' ) ;
706
+ patternSize , patternSolidity , 'fill' ) ;
662
707
} else {
663
708
Color . fill ( sel , fillColor ) ;
664
709
}
0 commit comments