diff --git a/src/components/drawing/index.js b/src/components/drawing/index.js index 3aa65a573d6..c97bfb1189b 100644 --- a/src/components/drawing/index.js +++ b/src/components/drawing/index.js @@ -354,185 +354,6 @@ drawing.gradient = function(sel, gd, gradientID, type, colorscale, prop) { fullLayout._gradientUrlQueryParts[k] = 1; }; -/** - * pattern: create and apply a pattern fill - * - * @param {object} sel: d3 selection to apply this pattern to - * You can use `selection.call(Drawing.pattern, ...)` - * @param {DOM element} gd: the graph div `sel` is part of - * @param {string} patternID: a unique (within this plot) identifier - * for this pattern, so that we don't create unnecessary definitions - * @param {string} bgcolor: background color for this pattern - * @param {string} fgcolor: foreground color for this pattern - * @param {number} size: size of unit squares for repetition of this pattern - * @param {number} solidity: how solid lines of this pattern are - * @param {string} prop: the property to apply to, 'fill' or 'stroke' - */ -drawing.pattern = function(sel, gd, patternID, shape, bgcolor, fgcolor, size, solidity, prop) { - var fullLayout = gd._fullLayout; - var fullID = 'p' + fullLayout._uid + '-' + patternID; - var width, height; - - // linear interpolation - var linearFn = function(x, x0, x1, y0, y1) { - return y0 + (y1 - y0) * (x - x0) / (x1 - x0); - }; - - var path, linewidth, radius; - var patternTag; - var patternAttrs = {}; - switch(shape) { - case '/': - width = size * Math.sqrt(2); - height = size * Math.sqrt(2); - path = 'M-' + (width / 4) + ',' + (height / 4) + 'l' + (width / 2) + ',-' + (height / 2) + - 'M0,' + height + 'L' + width + ',0' + - 'M' + (width / 4 * 3) + ',' + (height / 4 * 5) + 'l' + (width / 2) + ',-' + (height / 2); - linewidth = solidity * size; - patternTag = 'path'; - patternAttrs = { - 'd': path, - 'stroke': fgcolor, - 'stroke-width': linewidth + 'px' - }; - break; - case '\\': - width = size * Math.sqrt(2); - height = size * Math.sqrt(2); - path = 'M' + (width / 4 * 3) + ',-' + (height / 4) + 'l' + (width / 2) + ',' + (height / 2) + - 'M0,0L' + width + ',' + height + - 'M-' + (width / 4) + ',' + (height / 4 * 3) + 'l' + (width / 2) + ',' + (height / 2); - linewidth = solidity * size; - patternTag = 'path'; - patternAttrs = { - 'd': path, - 'stroke': fgcolor, - 'stroke-width': linewidth + 'px' - }; - break; - case 'x': - width = size * Math.sqrt(2); - height = size * Math.sqrt(2); - path = 'M-' + (width / 4) + ',' + (height / 4) + 'l' + (width / 2) + ',-' + (height / 2) + - 'M0,' + height + 'L' + width + ',0' + - 'M' + (width / 4 * 3) + ',' + (height / 4 * 5) + 'l' + (width / 2) + ',-' + (height / 2) + - 'M' + (width / 4 * 3) + ',-' + (height / 4) + 'l' + (width / 2) + ',' + (height / 2) + - 'M0,0L' + width + ',' + height + - 'M-' + (width / 4) + ',' + (height / 4 * 3) + 'l' + (width / 2) + ',' + (height / 2); - linewidth = size - size * Math.sqrt(1.0 - solidity); - patternTag = 'path'; - patternAttrs = { - 'd': path, - 'stroke': fgcolor, - 'stroke-width': linewidth + 'px' - }; - break; - case '|': - width = size; - height = size; - patternTag = 'path'; - path = 'M' + (width / 2) + ',0L' + (width / 2) + ',' + height; - linewidth = solidity * size; - patternTag = 'path'; - patternAttrs = { - 'd': path, - 'stroke': fgcolor, - 'stroke-width': linewidth + 'px' - }; - break; - case '-': - width = size; - height = size; - patternTag = 'path'; - path = 'M0,' + (height / 2) + 'L' + width + ',' + (height / 2); - linewidth = solidity * size; - patternTag = 'path'; - patternAttrs = { - 'd': path, - 'stroke': fgcolor, - 'stroke-width': linewidth + 'px' - }; - break; - case '+': - width = size; - height = size; - patternTag = 'path'; - path = 'M' + (width / 2) + ',0L' + (width / 2) + ',' + height + - 'M0,' + (height / 2) + 'L' + width + ',' + (height / 2); - linewidth = size - size * Math.sqrt(1.0 - solidity); - patternTag = 'path'; - patternAttrs = { - 'd': path, - 'stroke': fgcolor, - 'stroke-width': linewidth + 'px' - }; - break; - case '.': - width = size; - height = size; - if(solidity < Math.PI / 4) { - radius = Math.sqrt(solidity * size * size / Math.PI); - } else { - radius = linearFn(solidity, Math.PI / 4, 1.0, size / 2, size / Math.sqrt(2)); - } - patternTag = 'circle'; - patternAttrs = { - 'cx': width / 2, - 'cy': height / 2, - 'r': radius, - 'fill': fgcolor - }; - break; - } - - var pattern = fullLayout._defs.select('.patterns') - .selectAll('#' + fullID) - .data([shape + ';' + bgcolor + ';' + fgcolor + ';' + size + ';' + solidity], Lib.identity); - - pattern.exit().remove(); - - pattern.enter() - .append('pattern') - .each(function() { - var el = d3.select(this); - - el.attr({ - 'id': fullID, - 'width': width + 'px', - 'height': height + 'px', - 'patternUnits': 'userSpaceOnUse' - }); - - if(bgcolor) { - var rects = el.selectAll('rect').data([0]); - rects.exit().remove(); - rects.enter() - .append('rect') - .attr({ - 'width': width + 'px', - 'height': height + 'px', - 'fill': bgcolor - }); - } - - var patterns = el.selectAll(patternTag).data([0]); - patterns.exit().remove(); - patterns.enter() - .append(patternTag) - .attr(patternAttrs); - }); - - sel.style(prop, getFullUrl(fullID, gd)) - .style(prop + '-opacity', null); - - sel.classed('pattern_filled', true); - var className2query = function(s) { - return '.' + s.attr('class').replace(/\s/g, '.'); - }; - var k = className2query(d3.select(sel.node().parentNode)) + '>.pattern_filled'; - fullLayout._patternUrlQueryParts[k] = 1; -}; - /* * Make the gradients container and clear out any previous gradients. * We never collect all the gradients we need in one place, @@ -551,23 +372,6 @@ drawing.initGradients = function(gd) { fullLayout._gradientUrlQueryParts = {}; }; -drawing.initPatterns = function(gd) { - var fullLayout = gd._fullLayout; - - var patternsGroup = Lib.ensureSingle(fullLayout._defs, 'g', 'patterns'); - patternsGroup.selectAll('pattern').remove(); - - // initialize stash of query parts filled in Drawing.pattern, - // used to fix URL strings during image exports - fullLayout._patternUrlQueryParts = {}; -}; - -drawing.getPatternAttr = function(mp, i, dflt) { - if(mp && Lib.isArrayOrTypedArray(mp)) { - return i < mp.length ? mp[i] : dflt; - } - return mp; -}; drawing.pointStyle = function(s, trace, gd) { if(!s.size()) return; @@ -673,14 +477,11 @@ drawing.singlePointStyle = function(d, sel, trace, fns, gd) { // for legend - arrays will propagate through here, but we don't need // to treat it as per-point. - if(Lib.isArrayOrTypedArray(gradientType)) { + if(Array.isArray(gradientType)) { gradientType = gradientType[0]; if(!gradientInfo[gradientType]) gradientType = 0; } - var markerPattern = marker.pattern; - var patternShape = markerPattern && drawing.getPatternAttr(markerPattern.shape, d.i, ''); - if(gradientType && gradientType !== 'none') { var gradientColor = d.mgc; if(gradientColor) perPointGradient = true; @@ -691,20 +492,6 @@ drawing.singlePointStyle = function(d, sel, trace, fns, gd) { drawing.gradient(sel, gd, gradientID, gradientType, [[0, gradientColor], [1, fillColor]], 'fill'); - } else if(patternShape) { - var patternBGColor = drawing.getPatternAttr(markerPattern.bgcolor, d.i, null); - var patternSize = drawing.getPatternAttr(markerPattern.size, d.i, 8); - var patternSolidity = drawing.getPatternAttr(markerPattern.solidity, d.i, 0.3); - var perPointPattern = Lib.isArrayOrTypedArray(markerPattern.shape) || - Lib.isArrayOrTypedArray(markerPattern.bgcolor) || - Lib.isArrayOrTypedArray(markerPattern.size) || - Lib.isArrayOrTypedArray(markerPattern.solidity); - - var patternID = trace.uid; - if(perPointPattern) patternID += '-' + d.i; - - drawing.pattern(sel, gd, patternID, patternShape, patternBGColor, fillColor, - patternSize, patternSolidity, 'fill'); } else { Color.fill(sel, fillColor); } diff --git a/src/components/legend/style.js b/src/components/legend/style.js index 43fb10ffaa1..0ef881e9af4 100644 --- a/src/components/legend/style.js +++ b/src/components/legend/style.js @@ -357,23 +357,8 @@ module.exports = function style(s, gd, legend) { var d0 = d[0]; var w = boundLineWidth(d0.mlw, marker.line, MAX_MARKER_LINE_WIDTH, CST_MARKER_LINE_WIDTH); - p.style('stroke-width', w + 'px'); - - var fillColor = d0.mc || marker.color; - - var markerPattern = marker.pattern; - var patternShape = markerPattern && Drawing.getPatternAttr(markerPattern.shape, 0, ''); - - if(patternShape) { - var patternBGColor = Drawing.getPatternAttr(markerPattern.bgcolor, 0, null); - var patternSize = Math.min(12, Drawing.getPatternAttr(markerPattern.size, 0, 8)); - var patternSolidity = Drawing.getPatternAttr(markerPattern.solidity, 0, 0.3); - var patternID = 'legend-' + trace.uid; - p.call(Drawing.pattern, gd, patternID, patternShape, patternBGColor, - fillColor, patternSize, patternSolidity, 'fill'); - } else { - p.call(Color.fill, fillColor); - } + p.style('stroke-width', w + 'px') + .call(Color.fill, d0.mc || marker.color); if(w) Color.stroke(p, d0.mlc || markerLine.color); }); diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index 03397d85096..5707d741951 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -144,9 +144,8 @@ function _doPlot(gd, data, layout, config) { } } - // clear gradient and pattern defs on each .plot call, because we know we'll loop through all traces + // clear gradient defs on each .plot call, because we know we'll loop through all traces Drawing.initGradients(gd); - Drawing.initPatterns(gd); // save initial show spikes once per graph if(graphWasEmpty) Axes.saveShowSpikeInitial(gd); diff --git a/src/snapshot/tosvg.js b/src/snapshot/tosvg.js index 34ebfdc5f8d..c391cc02dfd 100644 --- a/src/snapshot/tosvg.js +++ b/src/snapshot/tosvg.js @@ -33,7 +33,7 @@ module.exports = function toSVG(gd, format, scale) { var toppaper = fullLayout._toppaper; var width = fullLayout.width; var height = fullLayout.height; - var i, k; + var i; // make background color a rect in the svg, then revert after scraping // all other alterations have been dealt with by properly preparing the svg @@ -106,31 +106,28 @@ module.exports = function toSVG(gd, format, scale) { } }); - var queryParts = []; - if(fullLayout._gradientUrlQueryParts) { - for(k in fullLayout._gradientUrlQueryParts) queryParts.push(k); - } - - if(fullLayout._patternUrlQueryParts) { - for(k in fullLayout._patternUrlQueryParts) queryParts.push(k); - } - - if(queryParts.length) { - svg.selectAll(queryParts.join(',')).each(function() { - var pt = d3.select(this); - // similar to font family styles above, - // we must remove " after the SVG DOM has been serialized - var fill = this.style.fill; - if(fill && fill.indexOf('url(') !== -1) { - pt.style('fill', fill.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB)); - } - - var stroke = this.style.stroke; - if(stroke && stroke.indexOf('url(') !== -1) { - pt.style('stroke', stroke.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB)); - } - }); + if(fullLayout._gradientUrlQueryParts) { + var queryParts = []; + for(var k in fullLayout._gradientUrlQueryParts) queryParts.push(k); + + if(queryParts.length) { + svg.selectAll(queryParts.join(',')).each(function() { + var pt = d3.select(this); + + // similar to font family styles above, + // we must remove " after the SVG DOM has been serialized + var fill = this.style.fill; + if(fill && fill.indexOf('url(') !== -1) { + pt.style('fill', fill.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB)); + } + + var stroke = this.style.stroke; + if(stroke && stroke.indexOf('url(') !== -1) { + pt.style('stroke', stroke.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB)); + } + }); + } } if(format === 'pdf' || format === 'eps') { diff --git a/src/traces/bar/attributes.js b/src/traces/bar/attributes.js index 3e32060afd2..01b0b752d18 100644 --- a/src/traces/bar/attributes.js +++ b/src/traces/bar/attributes.js @@ -39,54 +39,6 @@ var marker = extendFlat({ max: 1, editType: 'style', description: 'Sets the opacity of the bars.' - }, - pattern: { - shape: { - valType: 'enumerated', - values: ['', '/', '\\', 'x', '-', '|', '+', '.'], - dflt: '', - arrayOk: true, - editType: 'style', - description: [ - 'Sets the shape of the pattern fill.', - 'By default, no pattern is used for filling the area.', - ].join(' ') - }, - bgcolor: { - valType: 'color', - arrayOk: true, - editType: 'style', - description: [ - 'Sets the background color of the pattern fill.', - 'Defaults to a transparent background.', - ].join(' ') - }, - size: { - valType: 'number', - min: 0, - dflt: 8, - arrayOk: true, - editType: 'style', - description: [ - 'Sets the size of unit squares of the pattern fill in pixels,', - 'which corresponds to the interval of repetition of the pattern.', - ].join(' ') - }, - solidity: { - valType: 'number', - min: 0, - max: 1, - dflt: 0.3, - arrayOk: true, - editType: 'style', - description: [ - 'Sets the solidity of the pattern fill.', - 'Solidity is roughly proportional to the ratio of the area filled by the pattern.', - 'Solidity of 0 shows only the background color without pattern', - 'and solidty of 1 shows only the foreground color without pattern.', - ].join(' ') - }, - editType: 'style' } }); diff --git a/src/traces/bar/style_defaults.js b/src/traces/bar/style_defaults.js index b9c20eb7d59..20378dc7126 100644 --- a/src/traces/bar/style_defaults.js +++ b/src/traces/bar/style_defaults.js @@ -23,12 +23,6 @@ module.exports = function handleStyleDefaults(traceIn, traceOut, coerce, default coerce('marker.line.width'); coerce('marker.opacity'); - var patternShape = coerce('marker.pattern.shape'); - if(patternShape) { - coerce('marker.pattern.bgcolor'); - coerce('marker.pattern.size'); - coerce('marker.pattern.solidity'); - } coerce('selected.marker.color'); coerce('unselected.marker.color'); }; diff --git a/test/image/baselines/bar_patternfill.png b/test/image/baselines/bar_patternfill.png deleted file mode 100644 index 0edc8b1dc6e..00000000000 Binary files a/test/image/baselines/bar_patternfill.png and /dev/null differ diff --git a/test/image/mocks/bar_patternfill.json b/test/image/mocks/bar_patternfill.json deleted file mode 100644 index b25cd4f3e0c..00000000000 --- a/test/image/mocks/bar_patternfill.json +++ /dev/null @@ -1,125 +0,0 @@ -{ - "data": [ - { - "x": [ - "Area 1", - "Area 2", - "Area 3", - "Area 4", - "Area 5" - ], - "y": [ - 20, - 14, - 23, - 30, - 5 - ], - "name": "Product A", - "type": "bar", - "marker": { - "color": "#4477AA", - "line": { - "color": "#4477AA", - "width": 1 - }, - "pattern": { - "shape": "/" - } - } - }, - { - "x": [ - "Area 1", - "Area 2", - "Area 3", - "Area 4", - "Area 5" - ], - "y": [ - 12, - 18, - 29, - 10, - 23 - ], - "name": "Product B", - "type": "bar", - "marker": { - "color": "#CCBB44", - "line": { - "color": "#CCBB44", - "width": 1 - }, - "pattern": { - "shape": "\\" - } - } - }, - { - "x": [ - "Area 1", - "Area 2", - "Area 3", - "Area 4", - "Area 5" - ], - "y": [ - 30, - 23, - 22, - 33, - 15 - ], - "name": "Product C", - "type": "bar", - "marker": { - "color": "#EE6677", - "line": { - "color": "#EE6677", - "width": 1 - }, - "pattern": { - "shape": ["|", "-", "+", "x", "."] - } - } - }, - { - "x": [ - "Area 1", - "Area 2", - "Area 3", - "Area 4", - "Area 5" - ], - "y": [ - 18, - 29, - 31, - 20, - 23 - ], - "name": "Product D", - "type": "bar", - "marker": { - "color": ["#061a0a", "#124d1d", "#1d802f", "#29b342", "#35e655"], - "line": { - "color": ["#061a0a", "#124d1d", "#1d802f", "#29b342", "#35e655"], - "width": 1 - }, - "pattern": { - "shape": ["/", "\\", "x", ".", "+"], - "bgcolor": "#c6eff5", - "size": [4, 6, 8, 10, 12], - "solidity": [0.1, 0.3, 0.5, 0.7, 0.9] - } - } - } - ], - "layout": { - "xaxis": { - "type": "category" - }, - "barmode": "stack" - } -} diff --git a/test/jasmine/tests/mock_test.js b/test/jasmine/tests/mock_test.js index 3898625f1b0..44811150551 100644 --- a/test/jasmine/tests/mock_test.js +++ b/test/jasmine/tests/mock_test.js @@ -126,7 +126,6 @@ var list = [ 'bar_annotation_max_range_eq_category', 'bar_multiline_labels', 'bar_nonnumeric_sizes', - 'bar_patternfill', 'bar_show_narrow', 'bar_stack-with-gaps', 'bar_stackrelative_negative', @@ -1215,7 +1214,6 @@ figs['bar_marker_array'] = require('@mocks/bar_marker_array'); figs['bar_annotation_max_range_eq_category'] = require('@mocks/bar_annotation_max_range_eq_category'); figs['bar_multiline_labels'] = require('@mocks/bar_multiline_labels'); figs['bar_nonnumeric_sizes'] = require('@mocks/bar_nonnumeric_sizes'); -figs['bar_patternfill'] = require('@mocks/bar_patternfill'); figs['bar_show_narrow'] = require('@mocks/bar_show_narrow'); figs['bar_stack-with-gaps'] = require('@mocks/bar_stack-with-gaps'); figs['bar_stackrelative_negative'] = require('@mocks/bar_stackrelative_negative');