diff --git a/draftlogs/6800_add.md b/draftlogs/6800_add.md new file mode 100644 index 00000000000..54bf252d0ea --- /dev/null +++ b/draftlogs/6800_add.md @@ -0,0 +1 @@ + - Add `align` option to Sankey nodes to control horizontal alignment [[#6800](https://github.com/plotly/plotly.js/pull/6800)] diff --git a/src/traces/sankey/attributes.js b/src/traces/sankey/attributes.js index e717d5029d3..e792a3b3234 100644 --- a/src/traces/sankey/attributes.js +++ b/src/traces/sankey/attributes.js @@ -164,6 +164,12 @@ var attrs = module.exports = overrideAll({ description: 'Variables `sourceLinks` and `targetLinks` are arrays of link objects.', keys: ['value', 'label'] }), + align: { + valType: 'enumerated', + values: ['justify', 'left', 'right', 'center'], + dflt: 'justify', + description: 'Sets the alignment method used to position the nodes along the horizontal axis.' + }, description: 'The nodes of the Sankey plot.' }, diff --git a/src/traces/sankey/defaults.js b/src/traces/sankey/defaults.js index 01fc14f6fa4..3b8780f376e 100644 --- a/src/traces/sankey/defaults.js +++ b/src/traces/sankey/defaults.js @@ -34,6 +34,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout coerceNode('hoverinfo', traceIn.hoverinfo); handleHoverLabelDefaults(nodeIn, nodeOut, coerceNode, hoverlabelDefault); coerceNode('hovertemplate'); + coerceNode('align'); var colors = layout.colorway; diff --git a/src/traces/sankey/render.js b/src/traces/sankey/render.js index f84a1edbba7..0894b058c27 100644 --- a/src/traces/sankey/render.js +++ b/src/traces/sankey/render.js @@ -35,6 +35,12 @@ function sankeyModel(layout, d, traceIndex) { var horizontal = trace.orientation === 'h'; var nodePad = trace.node.pad; var nodeThickness = trace.node.thickness; + var nodeAlign = { + justify: d3Sankey.sankeyJustify, + left: d3Sankey.sankeyLeft, + right: d3Sankey.sankeyRight, + center: d3Sankey.sankeyCenter + }[trace.node.align]; var width = layout.width * (domain.x[1] - domain.x[0]); var height = layout.height * (domain.y[1] - domain.y[0]); @@ -61,6 +67,7 @@ function sankeyModel(layout, d, traceIndex) { .nodeId(function(d) { return d.pointNumber; }) + .nodeAlign(nodeAlign) .nodes(nodes) .links(links); diff --git a/test/image/baselines/sankey_align_center.png b/test/image/baselines/sankey_align_center.png new file mode 100644 index 00000000000..ec1cdc2e74d Binary files /dev/null and b/test/image/baselines/sankey_align_center.png differ diff --git a/test/image/baselines/sankey_align_justify.png b/test/image/baselines/sankey_align_justify.png new file mode 100644 index 00000000000..9113df3b924 Binary files /dev/null and b/test/image/baselines/sankey_align_justify.png differ diff --git a/test/image/baselines/sankey_align_left.png b/test/image/baselines/sankey_align_left.png new file mode 100644 index 00000000000..0022c7589cc Binary files /dev/null and b/test/image/baselines/sankey_align_left.png differ diff --git a/test/image/baselines/sankey_align_right.png b/test/image/baselines/sankey_align_right.png new file mode 100644 index 00000000000..ae0552ddedf Binary files /dev/null and b/test/image/baselines/sankey_align_right.png differ diff --git a/test/image/baselines/zz-sankey_circular_align_right.png b/test/image/baselines/zz-sankey_circular_align_right.png new file mode 100644 index 00000000000..39edbe3c98f Binary files /dev/null and b/test/image/baselines/zz-sankey_circular_align_right.png differ diff --git a/test/image/mocks/sankey_align_center.json b/test/image/mocks/sankey_align_center.json new file mode 100644 index 00000000000..c8a023fefe9 --- /dev/null +++ b/test/image/mocks/sankey_align_center.json @@ -0,0 +1,26 @@ +{ + "data": [ + { + "type": "sankey", + "node": { + "label": ["0", "1", "2", "3", "4", "5"], + "align": "center" + }, + "link": { + "source": [ + 0, 1, 4, 2, 1 + ], + "target": [ + 1, 4, 5, 4, 3 + ], + "value": [ + 4, 2, 3, 1, 2 + ] + } + }], + "layout": { + "title": {"text": "Sankey with center aligned nodes"}, + "width": 800, + "height": 800 + } +} diff --git a/test/image/mocks/sankey_align_justify.json b/test/image/mocks/sankey_align_justify.json new file mode 100644 index 00000000000..b1d9805f5c9 --- /dev/null +++ b/test/image/mocks/sankey_align_justify.json @@ -0,0 +1,26 @@ +{ + "data": [ + { + "type": "sankey", + "node": { + "label": ["0", "1", "2", "3", "4", "5"], + "align": "justify" + }, + "link": { + "source": [ + 0, 1, 4, 2, 1 + ], + "target": [ + 1, 4, 5, 4, 3 + ], + "value": [ + 4, 2, 3, 1, 2 + ] + } + }], + "layout": { + "title": {"text": "Sankey with justified node alignment"}, + "width": 800, + "height": 800 + } +} diff --git a/test/image/mocks/sankey_align_left.json b/test/image/mocks/sankey_align_left.json new file mode 100644 index 00000000000..85baa4b48a1 --- /dev/null +++ b/test/image/mocks/sankey_align_left.json @@ -0,0 +1,26 @@ +{ + "data": [ + { + "type": "sankey", + "node": { + "label": ["0", "1", "2", "3", "4", "5"], + "align": "left" + }, + "link": { + "source": [ + 0, 1, 4, 2, 1 + ], + "target": [ + 1, 4, 5, 4, 3 + ], + "value": [ + 4, 2, 3, 1, 2 + ] + } + }], + "layout": { + "title": {"text": "Sankey with left aligned nodes"}, + "width": 800, + "height": 800 + } +} diff --git a/test/image/mocks/sankey_align_right.json b/test/image/mocks/sankey_align_right.json new file mode 100644 index 00000000000..336c3e6e576 --- /dev/null +++ b/test/image/mocks/sankey_align_right.json @@ -0,0 +1,26 @@ +{ + "data": [ + { + "type": "sankey", + "node": { + "label": ["0", "1", "2", "3", "4", "5"], + "align": "right" + }, + "link": { + "source": [ + 0, 1, 4, 2, 1 + ], + "target": [ + 1, 4, 5, 4, 3 + ], + "value": [ + 4, 2, 3, 1, 2 + ] + } + }], + "layout": { + "title": {"text": "Sankey with right aligned nodes"}, + "width": 800, + "height": 800 + } +} diff --git a/test/image/mocks/zz-sankey_circular_align_right.json b/test/image/mocks/zz-sankey_circular_align_right.json new file mode 100644 index 00000000000..0dc9255fd5f --- /dev/null +++ b/test/image/mocks/zz-sankey_circular_align_right.json @@ -0,0 +1,27 @@ +{ + "data": [ + { + "type": "sankey", + "node": { + "pad": 5, + "align": "right", + "label": ["0", "1", "2", "3", "4", "5", "6"] + }, + "link": { + "source": [ + 0, 0, 1, 2, 5, 4, 3 + ], + "target": [ + 5, 3, 4, 3, 0, 2, 2 + ], + "value": [ + 1, 2, 1, 1, 1, 1, 1 + ] + } + }], + "layout": { + "title": {"text": "Sankey with circular data, aligned right"}, + "width": 800, + "height": 800 + } +} diff --git a/test/plot-schema.json b/test/plot-schema.json index 4970a9f5752..9ad961d8701 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -44358,6 +44358,18 @@ "valType": "string" }, "node": { + "align": { + "description": "Sets the alignment method used to position the nodes along the horizontal axis.", + "dflt": "justify", + "editType": "calc", + "valType": "enumerated", + "values": [ + "justify", + "left", + "right", + "center" + ] + }, "color": { "arrayOk": true, "description": "Sets the `node` color. It can be a single value, or an array for specifying color for each `node`. If `node.color` is omitted, then the default `Plotly` color palette will be cycled through to have a variety of colors. These defaults are not fully opaque, to allow some visibility of what is beneath the node.",