-
Notifications
You must be signed in to change notification settings - Fork 256
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unwanted circle on link path #111
Comments
It turned out that this is in fact an issue with the current implementation which uses the stroke width to draw the links - which breaks down if the link is shorter than wide. The solution is to actually draw the outline of the link. You can find my full solution here: https://stackoverflow.com/a/72593081/2230045 Feel free to use and adapt this code: /** @type {Function} [linkWidth=d => '0.9'] - A function to return a float to scale the link width. */
export let linkWidth = (d) => 0.9;
/**
* This function is a drop in replacement for d3.sankeyLinkHorizontal().
* Except any accessors/options.
* @param {Object} link - Link object.
* @param {Number} link.y0 - y coordinate for the start of the link.
* @param {Number} link.y1 - y coordinate for the end of the link.
* @param {Number} link.width - Width of the link.
* @param {Object} link.source - Source node object.
* @param {Number} link.source.x1 - x coordinate for the start of the link.
* @param {Object} link.target - Target node object.
* @param {Number} link.target.x0 - x coordinate for the end of the link.
**/
function sankeyLinkPathHorizontal(link) {
// Start and end of the link
let sx1 = link.source.x1;
let tx0 = link.target.x0 + 1;
// All four outer corners of the link
// where e.g. lsy0 is the upper corner of the link on the source side
let lsy0 = link.y0 - (link.width / 2) * linkWidth(link);
let lsy1 = link.y0 + (link.width / 2) * linkWidth(link);
let lty0 = link.y1 - (link.width / 2) * linkWidth(link);
let lty1 = link.y1 + (link.width / 2) * linkWidth(link);
// Center (x) of the link
let lcx = sx1 + (tx0 - sx1) / 2;
// Define outline of link as path
let path = d3.path();
path.moveTo(sx1, lsy0);
path.bezierCurveTo(lcx, lsy0, lcx, lty0, tx0, lty0);
path.lineTo(tx0, lty1);
path.bezierCurveTo(lcx, lty1, lcx, lsy1, sx1, lsy1);
path.lineTo(sx1, lsy0);
return path.toString();
}
/**
* This function is a drop in replacement for d3.sankeyLinkVertical().
* Except any accessors/options.
* @param {Object} link - Link object.
* @param {Number} link.y0 - y coordinate for the start of the link.
* @param {Number} link.y1 - y coordinate for the end of the link.
* @param {Number} link.width - Width of the link.
* @param {Object} link.source - Source node object.
* @param {Number} link.source.x1 - x coordinate for the start of the link.
* @param {Object} link.target - Target node object.
* @param {Number} link.target.x0 - x coordinate for the end of the link.
**/
function sankeyLinkPathVertical(link) {
// Start and end of the link
let sy1 = link.source.x1;
let ty0 = link.target.x0 + 1;
// All four outer corners of the link
// where e.g. lsx0 is the right corner of the link on the source side
let lsx0 = link.y0 - (link.width / 2) * linkWidth(link);
let lsx1 = link.y0 + (link.width / 2) * linkWidth(link);
let ltx0 = link.y1 - (link.width / 2) * linkWidth(link);
let ltx1 = link.y1 + (link.width / 2) * linkWidth(link);
// Center (y) of the link
let lcy = sy1 + (ty0 - sy1) / 2;
// Define outline of link as path
let path = d3.path();
path.moveTo(lsx0, sy1);
path.bezierCurveTo(lsx0, lcy, ltx0, lcy, ltx0, ty0);
path.lineTo(ltx1, ty0);
path.bezierCurveTo(ltx1, lcy, lsx1, lcy, lsx1, sy1);
path.lineTo(lsx0, sy1);
return path.toString();
} |
I made a simple first sankey diagram but on some link paths I'm getting unwanted paths. When I play around with the path size it looks like there is a circle in the middle of the path which is as big as the stroke width. So if the path is shorter than the stroke width, then you can see that circle.
Here a jsfiddle with the shown sankey diagram: https://jsfiddle.net/a2oc3nr1/9/
Interestingly, if I put the exact path which I marked in the image above alone into a jsfiddle, the issue is not reproducible.
https://jsfiddle.net/8k5xog3z/1/
It seems that the example provided here also suffers the same issue:
https://observablehq.com/@d3/parallel-sets?collection=@d3/d3-sankey
I could not figure out how to avoid / fix that.
The text was updated successfully, but these errors were encountered: