diff --git a/draftlogs/8084_add.md b/draftlogs/8084_add.md new file mode 100644 index 00000000000..e2ac4a59a54 --- /dev/null +++ b/draftlogs/8084_add.md @@ -0,0 +1 @@ + - Add `fillpattern` support for `scatterternary` trace [[#8084](https://github.com/plotly/plotly.js/pull/8084)] \ No newline at end of file diff --git a/src/traces/scatterternary/attributes.js b/src/traces/scatterternary/attributes.js index 315c04c4144..2fb604b9c04 100644 --- a/src/traces/scatterternary/attributes.js +++ b/src/traces/scatterternary/attributes.js @@ -111,6 +111,7 @@ module.exports = { ].join(' ') }), fillcolor: makeFillcolorAttr(), + fillpattern: scatterAttrs.fillpattern, marker: extendFlat( { symbol: scatterMarkerAttrs.symbol, diff --git a/src/traces/scatterternary/defaults.js b/src/traces/scatterternary/defaults.js index 6be1e2d0363..6ea22affdda 100644 --- a/src/traces/scatterternary/defaults.js +++ b/src/traces/scatterternary/defaults.js @@ -1,6 +1,7 @@ 'use strict'; var Lib = require('../../lib'); +var coercePattern = require('../../lib').coercePattern; var constants = require('../scatter/constants'); var subTypes = require('../scatter/subtypes'); @@ -85,6 +86,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout if (traceOut.fill !== 'none') { handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); if (!subTypes.hasLines(traceOut)) handleLineShapeDefaults(traceIn, traceOut, coerce); + coercePattern(coerce, 'fillpattern', traceOut.fillcolor, false); } if (traceOut.fill === 'tonext' || traceOut.fill === 'toself') { diff --git a/src/types/generated/schema.d.ts b/src/types/generated/schema.d.ts index 5283911ff43..99d24233f32 100644 --- a/src/types/generated/schema.d.ts +++ b/src/types/generated/schema.d.ts @@ -9559,6 +9559,8 @@ export interface ScatterternaryData { fill?: 'none' | 'toself' | 'tonext'; /** Sets the fill color. Defaults to a half-transparent variant of the line color, marker color, or marker line color, whichever is available. */ fillcolor?: Color; + /** Sets the pattern within the marker. */ + fillpattern?: Pattern; /** * Determines what trace information appears on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired. * @default 'all' diff --git a/test/image/baselines/ternary_fill_pattern.png b/test/image/baselines/ternary_fill_pattern.png new file mode 100644 index 00000000000..9bb80a62ad2 Binary files /dev/null and b/test/image/baselines/ternary_fill_pattern.png differ diff --git a/test/image/mocks/ternary_fill_pattern.json b/test/image/mocks/ternary_fill_pattern.json new file mode 100644 index 00000000000..da341505113 --- /dev/null +++ b/test/image/mocks/ternary_fill_pattern.json @@ -0,0 +1,87 @@ +{ + "data": [ + { + "type": "scatterternary", + "mode": "lines", + "a": [80, 65, 65, 80], + "b": [10, 25, 10, 10], + "c": [10, 10, 25, 10], + "fill": "toself", + "fillpattern": { + "fillmode": "overlay", + "shape": "/" + } + }, + { + "type": "scatterternary", + "mode": "lines", + "a": [10, 25, 10, 10], + "b": [80, 65, 65, 80], + "c": [10, 10, 25, 10], + "fill": "toself", + "fillpattern": { + "fillmode": "overlay", + "shape": "\\" + } + }, + { + "type": "scatterternary", + "mode": "lines", + "a": [10, 25, 10, 10], + "b": [10, 10, 25, 10], + "c": [80, 65, 65, 80], + "fill": "toself", + "fillpattern": { + "fillmode": "overlay", + "shape": "." + } + }, + { + "type": "scatterternary", + "subplot": "ternary2", + "mode": "lines", + "a": [50, 25, 25, 50], + "b": [25, 50, 25, 25], + "c": [25, 25, 50, 25], + "fill": "toself", + "fillpattern": { + "fillmode": "replace", + "solidity": 0.4, + "size": 12, + "shape": "-" + } + }, + { + "type": "scatterternary", + "subplot": "ternary2", + "mode": "lines", + "a": [70, 15, 15, 70], + "b": [15, 70, 15, 15], + "c": [15, 15, 70, 15], + "fill": "tonext", + "fillpattern": { + "fillmode": "replace", + "solidity": 0.4, + "size": 12, + "shape": "|" + } + } + ], + "layout": { + "title": { "text": "Pattern fill for scatterternary" }, + "width": 800, + "height": 400, + "ternary": { + "sum": 100, + "domain": { + "x": [0, 0.35] + } + }, + "ternary2": { + "sum": 100, + "domain": { + "x": [0.65, 1] + } + } + } +} diff --git a/test/jasmine/tests/scatterternary_test.js b/test/jasmine/tests/scatterternary_test.js index e04fc68b19d..233edfdc398 100644 --- a/test/jasmine/tests/scatterternary_test.js +++ b/test/jasmine/tests/scatterternary_test.js @@ -226,6 +226,92 @@ describe('scatterternary defaults', function() { supplyDefaults(traceIn, traceOut, defaultColor, layout); expect(traceOut.hoveron).toBe('points'); }); + + it('should coerce \'fillpattern\' defaults with *replace* fillpattern.fillmode', function() { + traceIn = { + a: [3, 1, 1], + b: [1, 3, 1], + c: [1, 1, 3], + mode: 'lines', + fill: 'toself', + fillcolor: 'green', + fillpattern: {shape: '+'} + }; + + supplyDefaults(traceIn, traceOut, defaultColor, layout); + + expect(traceOut.fillpattern.shape).toBe('+'); + expect(traceOut.fillpattern.fillmode).toBe('replace'); + expect(traceOut.fillpattern.bgcolor).toBeUndefined('transparent background'); + expect(traceOut.fillpattern.fgcolor).toBe('green'); + expect(traceOut.fillpattern.fgopacity).toBe(1); + expect(traceOut.fillpattern.size).toBe(8); + expect(traceOut.fillpattern.solidity).toBe(0.3); + }); + + it('should coerce \'fillpattern\' defaults with *overlay* fillpattern.fillmode', function() { + traceIn = { + a: [3, 1, 1], + b: [1, 3, 1], + c: [1, 1, 3], + mode: 'lines', + fill: 'toself', + fillcolor: 'green', + fillpattern: { + fillmode: 'overlay', + shape: '+' + } + }; + + supplyDefaults(traceIn, traceOut, defaultColor, layout); + + expect(traceOut.fillpattern.shape).toBe('+'); + expect(traceOut.fillpattern.bgcolor).toBe('green'); + expect(traceOut.fillpattern.fgcolor).toBe('rgb(255, 255, 255)'); + expect(traceOut.fillpattern.fgopacity).toBe(0.5); + }); + + it('should support a custom \'fillpattern.path\'', function() { + traceIn = { + a: [1, 2, 3], + b: [3, 2, 1], + c: [2, 2, 2], + mode: 'lines', + fill: 'toself', + fillcolor: 'green', + fillpattern: { + path: 'M0,0L8,0L8,4L0,4Z', + size: 12, + bgcolor: 'blue', + fgcolor: 'red', + fgopacity: 0.6 + } + }; + + supplyDefaults(traceIn, traceOut, defaultColor, layout); + + expect(traceOut.fillpattern.path).toBe('M0,0L8,0L8,4L0,4Z'); + expect(traceOut.fillpattern.size).toBe(12); + expect(traceOut.fillpattern.bgcolor).toBe('blue'); + expect(traceOut.fillpattern.fgcolor).toBe('red'); + expect(traceOut.fillpattern.fgopacity).toBe(0.6); + expect(traceOut.fillpattern.solidity).toBeUndefined(); + }); + + it('should not coerce \'fillpattern\' when \'fill\' is *none*', function() { + traceIn = { + a: [1, 2, 3], + b: [3, 2, 1], + c: [2, 2, 2], + mode: 'lines', + fill: 'none', + fillpattern: {shape: '+'} + }; + + supplyDefaults(traceIn, traceOut, defaultColor, layout); + + expect(traceOut.fillpattern).toBeUndefined(); + }); }); describe('scatterternary calc', function() { diff --git a/test/plot-schema.json b/test/plot-schema.json index 3f8728d1b01..ff446f9ea8a 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -71299,6 +71299,80 @@ "editType": "style", "valType": "color" }, + "fillpattern": { + "bgcolor": { + "arrayOk": true, + "description": "When there is no colorscale sets the color of background pattern fill. Defaults to a `marker.color` background when `fillmode` is *overlay*. Otherwise, defaults to a transparent background.", + "editType": "style", + "valType": "color" + }, + "description": "Sets the pattern within the marker.", + "editType": "style", + "fgcolor": { + "arrayOk": true, + "description": "When there is no colorscale sets the color of foreground pattern fill. Defaults to a `marker.color` background when `fillmode` is *replace*. Otherwise, defaults to dark grey or white to increase contrast with the `bgcolor`.", + "editType": "style", + "valType": "color" + }, + "fgopacity": { + "description": "Sets the opacity of the foreground pattern fill. Defaults to a 0.5 when `fillmode` is *overlay*. Otherwise, defaults to 1.", + "editType": "style", + "max": 1, + "min": 0, + "valType": "number" + }, + "fillmode": { + "description": "Determines whether `marker.color` should be used as a default to `bgcolor` or a `fgcolor`.", + "dflt": "replace", + "editType": "style", + "valType": "enumerated", + "values": [ + "replace", + "overlay" + ] + }, + "path": { + "arrayOk": true, + "description": "Sets a custom path for pattern fill. Use with no `shape` or `solidity`, provide an SVG path string for the regions of the square from (0,0) to (`size`,`size`) to color.", + "editType": "style", + "valType": "string" + }, + "role": "object", + "shape": { + "arrayOk": true, + "description": "Sets the shape of the pattern fill. By default, no pattern is used for filling the area.", + "dflt": "", + "editType": "style", + "valType": "enumerated", + "values": [ + "", + "/", + "\\", + "x", + "-", + "|", + "+", + "." + ] + }, + "size": { + "arrayOk": true, + "description": "Sets the size of unit squares of the pattern fill in pixels, which corresponds to the interval of repetition of the pattern.", + "dflt": 8, + "editType": "style", + "min": 0, + "valType": "number" + }, + "solidity": { + "arrayOk": true, + "description": "Sets the solidity of the pattern fill. Solidity is roughly the fraction 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.", + "dflt": 0.3, + "editType": "style", + "max": 1, + "min": 0, + "valType": "number" + } + }, "hoverinfo": { "arrayOk": true, "description": "Determines what trace information appears on hover. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired.",