Skip to content

Commit

Permalink
Merge pull request #5531 from plotly/sankey-text-and-shadow
Browse files Browse the repository at this point in the history
Fixup sankey text and shadow
  • Loading branch information
archmoj authored Mar 5, 2021
2 parents ed52205 + 2f38a9d commit ff0c00a
Show file tree
Hide file tree
Showing 22 changed files with 97 additions and 122 deletions.
10 changes: 6 additions & 4 deletions src/lib/svg_text_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -755,10 +755,12 @@ function alignHTMLWith(_base, container, options) {
};
}

exports.makeTextShadow = function(offset, color) {
var x = offset + 'px ';
var y = offset + 'px ';
var b = '1px ';
var onePx = '1px ';

exports.makeTextShadow = function(color) {
var x = onePx;
var y = onePx;
var b = onePx;
return x + y + b + color + ', ' +
'-' + x + '-' + y + b + color + ', ' +
x + '-' + y + b + color + ', ' +
Expand Down
2 changes: 1 addition & 1 deletion src/traces/parcats/parcats.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ function performPlot(parcatsModels, graphDiv, layout, svg) {
})
.attr('alignment-baseline', 'middle')

.style('text-shadow', svgTextUtils.makeTextShadow(1, paperColor))
.style('text-shadow', svgTextUtils.makeTextShadow(paperColor))
.style('fill', 'rgb(0, 0, 0)')
.attr('x',
function(d) {
Expand Down
2 changes: 1 addition & 1 deletion src/traces/parcoords/parcoords.js
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ module.exports = function parcoords(gd, cdModule, layout, callbacks) {
.attr('stroke-width', '1px');

axis.selectAll('text')
.style('text-shadow', svgTextUtils.makeTextShadow(1, paperColor))
.style('text-shadow', svgTextUtils.makeTextShadow(paperColor))
.style('cursor', 'default');

var axisHeading = axisOverlays.selectAll('.' + c.cn.axisHeading)
Expand Down
6 changes: 1 addition & 5 deletions src/traces/sankey/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ module.exports = {
sankeyNodeSet: 'sankey-node-set',
sankeyNode: 'sankey-node',
nodeRect: 'node-rect',
nodeCapture: 'node-capture',
nodeCentered: 'node-entered',
nodeLabelGuide: 'node-label-guide',
nodeLabel: 'node-label',
nodeLabelTextPath: 'node-label-text-path'
nodeLabel: 'node-label'
}
};
144 changes: 51 additions & 93 deletions src/traces/sankey/render.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
'use strict';

var c = require('./constants');
var d3Force = require('d3-force');
var interpolateNumber = require('d3-interpolate').interpolateNumber;
var d3 = require('@plotly/d3');
var d3Sankey = require('@plotly/d3-sankey');
var d3SankeyCircular = require('@plotly/d3-sankey-circular');

var c = require('./constants');
var tinycolor = require('tinycolor2');
var Color = require('../../components/color');
var Drawing = require('../../components/drawing');
var d3Sankey = require('@plotly/d3-sankey');
var d3SankeyCircular = require('@plotly/d3-sankey-circular');
var d3Force = require('d3-force');
var Lib = require('../../lib');
var strTranslate = Lib.strTranslate;
var strRotate = Lib.strRotate;
var gup = require('../../lib/gup');
var keyFun = gup.keyFun;
var repeat = gup.repeat;
var unwrap = gup.unwrap;
var interpolateNumber = require('d3-interpolate').interpolateNumber;
var svgTextUtils = require('../../lib/svg_text_utils');

var Registry = require('../../registry');

var alignmentConstants = require('../../constants/alignment');
var CAP_SHIFT = alignmentConstants.CAP_SHIFT;
var LINE_SPACING = alignmentConstants.LINE_SPACING;
var TEXTPAD = 3;

// view models

function sankeyModel(layout, d, traceIndex) {
Expand Down Expand Up @@ -547,22 +554,6 @@ function sankeyTransform(d) {
return offset + (d.horizontal ? 'matrix(1 0 0 1 0 0)' : 'matrix(0 1 1 0 0 0)');
}

function nodeCentering(d) {
return strTranslate(d.horizontal ? 0 : d.labelY, d.horizontal ? d.labelY : 0);
}

function textGuidePath(d) {
return d3.svg.line()([
[d.horizontal ? (d.left ? -d.sizeAcross : d.visibleWidth + c.nodeTextOffsetHorizontal) : c.nodeTextOffsetHorizontal, 0],
[d.horizontal ? (d.left ? - c.nodeTextOffsetHorizontal : d.sizeAcross) : d.visibleHeight - c.nodeTextOffsetHorizontal, 0]
]);
}

function sankeyInverseTransform(d) {return d.horizontal ? 'matrix(1 0 0 1 0 0)' : 'matrix(0 1 1 0 0 0)';}
function textFlip(d) {return d.horizontal ? 'scale(1 1)' : 'scale(-1 1)';}
function nodeTextColor(d) {return d.darkBackground && !d.horizontal ? 'rgb(255,255,255)' : 'rgb(0,0,0)';}
function nodeTextOffset(d) {return d.horizontal && d.left ? '100%' : '0%';}

// event handling

function attachPointerEvents(selection, sankey, eventSet) {
Expand Down Expand Up @@ -970,88 +961,55 @@ module.exports = function(gd, svg, calcData, layout, callbacks) {
.ease(c.ease).duration(c.duration)
.call(sizeNode);

var nodeCapture = sankeyNode.selectAll('.' + c.cn.nodeCapture)
.data(repeat);

nodeCapture.enter()
.append('rect')
.classed(c.cn.nodeCapture, true)
.style('fill-opacity', 0);

nodeCapture
.attr('x', function(d) {return d.zoneX;})
.attr('y', function(d) {return d.zoneY;})
.attr('width', function(d) {return d.zoneWidth;})
.attr('height', function(d) {return d.zoneHeight;});

var nodeCentered = sankeyNode.selectAll('.' + c.cn.nodeCentered)
.data(repeat);

nodeCentered.enter()
.append('g')
.classed(c.cn.nodeCentered, true)
.attr('transform', nodeCentering);

nodeCentered
.transition()
.ease(c.ease).duration(c.duration)
.attr('transform', nodeCentering);

var nodeLabelGuide = nodeCentered.selectAll('.' + c.cn.nodeLabelGuide)
.data(repeat);

nodeLabelGuide.enter()
.append('path')
.classed(c.cn.nodeLabelGuide, true)
.attr('id', function(d) {return d.uniqueNodeLabelPathId;})
.attr('d', textGuidePath)
.attr('transform', sankeyInverseTransform);

nodeLabelGuide
.transition()
.ease(c.ease).duration(c.duration)
.attr('d', textGuidePath)
.attr('transform', sankeyInverseTransform);

var nodeLabel = nodeCentered.selectAll('.' + c.cn.nodeLabel)
var nodeLabel = sankeyNode.selectAll('.' + c.cn.nodeLabel)
.data(repeat);

nodeLabel.enter()
.append('text')
.classed(c.cn.nodeLabel, true)
.attr('transform', textFlip)
.style('cursor', 'default')
.style('fill', 'black');
.style('cursor', 'default');

nodeLabel
.style('text-shadow', function(d) {
return d.horizontal ? svgTextUtils.makeTextShadow(1, '#fff') : 'none';
.attr('data-notex', 1) // prohibit tex interpretation until we can handle tex and regular text together
.text(function(d) { return d.node.label; })
.each(function(d) {
var e = d3.select(this);
Drawing.font(e, d.textFont);
svgTextUtils.convertToTspans(e, gd);
})
.each(function(d) {Drawing.font(nodeLabel, d.textFont);});

nodeLabel
.transition()
.ease(c.ease).duration(c.duration)
.attr('transform', textFlip);

var nodeLabelTextPath = nodeLabel.selectAll('.' + c.cn.nodeLabelTextPath)
.data(repeat);
.style('text-shadow', svgTextUtils.makeTextShadow(gd._fullLayout.paper_bgcolor))
.attr('text-anchor', function(d) {
return (d.horizontal && d.left) ? 'end' : 'start';
})
.attr('transform', function(d) {
var e = d3.select(this);
// how much to shift a multi-line label to center it vertically.
var nLines = svgTextUtils.lineCount(e);
var blockHeight = d.textFont.size * (
(nLines - 1) * LINE_SPACING - CAP_SHIFT
);

var posX = d.nodeLineWidth / 2 + TEXTPAD;
var posY = ((d.horizontal ? d.visibleHeight : d.visibleWidth) - blockHeight) / 2;
if(d.horizontal) {
if(d.left) {
posX = -posX;
} else {
posX += d.visibleWidth;
}
}

nodeLabelTextPath.enter()
.append('textPath')
.classed(c.cn.nodeLabelTextPath, true)
.attr('alignment-baseline', 'middle')
.attr('xlink:href', function(d) {return '#' + d.uniqueNodeLabelPathId;})
.attr('startOffset', nodeTextOffset)
.style('fill', nodeTextColor);
var flipText = d.horizontal ? '' : (
'scale(-1,1)' + strRotate(90)
);

nodeLabelTextPath
.text(function(d) {return d.horizontal || d.node.dy > 5 ? d.node.label : '';})
.attr('text-anchor', function(d) {return d.horizontal && d.left ? 'end' : 'start';});
return strTranslate(
d.horizontal ? posX : posY,
d.horizontal ? posY : posX
) + flipText;
});

nodeLabelTextPath
nodeLabel
.transition()
.ease(c.ease).duration(c.duration)
.attr('startOffset', nodeTextOffset)
.style('fill', nodeTextColor);
.ease(c.ease).duration(c.duration);
};
Binary file modified test/image/baselines/sankey_circular.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/sankey_circular_large.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/sankey_circular_process.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/sankey_circular_simple.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/sankey_circular_simple2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/sankey_energy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/sankey_energy_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/sankey_groups.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/sankey_large_padding.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/sankey_link_concentration.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/sankey_messy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/sankey_subplots.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/sankey_subplots_circular.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/sankey_x_y.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions test/image/mocks/sankey_energy_dark.json
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@
"height": 1000,
"paper_bgcolor": "rgba(0,0,0,1)",
"font": {
"color": "white",
"size": 10
},
"updatemenus": [
Expand Down
32 changes: 25 additions & 7 deletions test/image/mocks/sankey_subplots.json
Original file line number Diff line number Diff line change
@@ -1,40 +1,57 @@
{
"data": [{
"domain": {
"x": [0, 0.45]
"y": [0, 0.45]
},
"type": "sankey",
"orientation": "h",
"node": {
"line": {
"width": 4,
"color": "black"
},
"label": ["el1", "el2", "el3"]
"label": [
"<i>Rien ne se perd,<br>rien ne se crée,<br>tout se <b>transforme</b>.</i><sub>",
"H<sub>2</sub>O",
"<b>e<sup>iπ</sup> = cos i + i sin π</b>"
]
},
"link": {
"source": [0, 2],
"target": [1, 1],
"value": [120, 50],
"label": ["stram1", "stream2"]
},
"textfont": {
"color": "darkblue"
}
},
{
"domain": {
"x": [0.55, 1]
"y": [0.55, 1]
},
"type": "sankey",
"orientation": "h",
"orientation": "v",
"node": {
"thickness": 50,
"line": {
"width": 4,
"color": "black"
},
"label": ["el4", "el5", "el6"]
"label": [
"<i>Rien ne se perd,<br>rien ne se crée,<br>tout se <b>transforme</b>.</i><sub>",
"H<sub>2</sub>O",
"<b>e<sup>iπ</sup> = cos i + i sin π</b>"
]
},
"link": {
"source": [0, 2],
"target": [1, 1],
"value": [120, 50],
"label": ["stram4", "stream5"]
"label": ["stram1", "stream2"]
},
"textfont": {
"color": "darkblue"
}
},
{
Expand All @@ -44,7 +61,8 @@
],
"layout": {
"title": {"text": "Multiple Sankey plots"},
"autosize": true,
"width": 600,
"height": 600,
"showlegend": false
}
}
Loading

0 comments on commit ff0c00a

Please sign in to comment.