Skip to content

Commit 39e35cc

Browse files
committed
Change the interface of pattern fill and some fix
1 parent 863854f commit 39e35cc

File tree

6 files changed

+123
-75
lines changed

6 files changed

+123
-75
lines changed

src/components/drawing/index.js

Lines changed: 100 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

src/components/legend/style.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -368,16 +368,16 @@ module.exports = function style(s, gd, legend) {
368368
}
369369
return mp;
370370
};
371-
var markerPattern = marker.patternfill;
371+
var markerPattern = marker.pattern;
372372
var patternShape = markerPattern && getPatternAttr(markerPattern.shape, '');
373373

374374
if(patternShape) {
375375
var patternBGColor = getPatternAttr(markerPattern.bgcolor, null);
376-
var patternScale = getPatternAttr(markerPattern.scale, 1);
376+
var patternSize = getPatternAttr(markerPattern.size, 1);
377377
var patternSolidity = getPatternAttr(markerPattern.solidity, 1);
378378
var patternID = trace.uid;
379379
p.call(Drawing.pattern, gd, patternID, patternShape, patternBGColor,
380-
fillColor, patternScale, patternSolidity, 'fill');
380+
fillColor, patternSize, patternSolidity, 'fill');
381381
} else {
382382
p.call(Color.fill, fillColor);
383383
}

src/traces/bar/attributes.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ var marker = extendFlat({
4040
editType: 'style',
4141
description: 'Sets the opacity of the bars.'
4242
},
43-
patternfill: {
43+
pattern: {
4444
shape: {
4545
valType: 'enumerated',
4646
values: ['', '/', '\\', 'x', '-', '|', '+', '.'],
@@ -61,26 +61,29 @@ var marker = extendFlat({
6161
'Defaults to a transparent background.',
6262
].join(' ')
6363
},
64-
scale: {
64+
size: {
6565
valType: 'number',
6666
min: 0,
67-
dflt: 1,
67+
dflt: 8,
6868
arrayOk: true,
6969
editType: 'style',
7070
description: [
71-
'Sets the scale of the pattern fill.',
72-
'Defaults to 1.',
71+
'Sets the size of unit squares of the pattern fill in pixels,',
72+
'which corresponds to the interval of repetition of the pattern.',
7373
].join(' ')
7474
},
7575
solidity: {
7676
valType: 'number',
7777
min: 0,
78-
dflt: 1,
78+
max: 1,
79+
dflt: 0.3,
7980
arrayOk: true,
8081
editType: 'style',
8182
description: [
8283
'Sets the solidity of the pattern fill.',
83-
'Defaults to 1.',
84+
'Solidity is roughly proportional to the ratio of the area filled by the pattern.',
85+
'Solidity of 0 shows only the background color without pattern',
86+
'and solidty of 1 shows only the foreground color without pattern.',
8487
].join(' ')
8588
},
8689
editType: 'style'

src/traces/bar/style_defaults.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ module.exports = function handleStyleDefaults(traceIn, traceOut, coerce, default
2323

2424
coerce('marker.line.width');
2525
coerce('marker.opacity');
26-
coerce('marker.patternfill.shape');
27-
coerce('marker.patternfill.bgcolor');
28-
coerce('marker.patternfill.scale');
29-
coerce('marker.patternfill.solidity');
26+
coerce('marker.pattern.shape');
27+
coerce('marker.pattern.bgcolor');
28+
coerce('marker.pattern.size');
29+
coerce('marker.pattern.solidity');
3030
coerce('selected.marker.color');
3131
coerce('unselected.marker.color');
3232
};
33.9 KB
Loading

test/image/mocks/bar_patternfill.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"color": "#4477AA",
2424
"width": 1
2525
},
26-
"patternfill": {
26+
"pattern": {
2727
"shape": "/"
2828
}
2929
}
@@ -51,7 +51,7 @@
5151
"color": "#CCBB44",
5252
"width": 1
5353
},
54-
"patternfill": {
54+
"pattern": {
5555
"shape": "\\"
5656
}
5757
}
@@ -79,7 +79,7 @@
7979
"color": "#EE6677",
8080
"width": 1
8181
},
82-
"patternfill": {
82+
"pattern": {
8383
"shape": ["|", "-", "+", "x", "."]
8484
}
8585
}
@@ -107,11 +107,11 @@
107107
"color": ["#061a0a", "#124d1d", "#1d802f", "#29b342", "#35e655"],
108108
"width": 1
109109
},
110-
"patternfill": {
110+
"pattern": {
111111
"shape": ["/", "\\", "x", ".", "+"],
112112
"bgcolor": "#c6eff5",
113-
"scale": [0.7, 1.0, 1.2, 1.5, 2.0],
114-
"solidity": [2, 3, 4, 5, 6]
113+
"size": [4, 6, 8, 10, 12],
114+
"solidity": [0.1, 0.3, 0.5, 0.7, 0.9]
115115
}
116116
}
117117
}

0 commit comments

Comments
 (0)