我正在通過 SVG 拼湊一個桑基圖,但突然在某些未知條件下,其中一條路徑顯示了一個不應該有的圓圈。
我試圖從我的 SVG 中洗掉盡可能多的內容,但進一步洗掉任何內容會使這不再可重現。
在這里你可以看到我縮小的 SVG 影像。黑色路徑元素是有問題的元素。我手動標記了路徑筆劃元素應該結束的位置,但不知何故,它顯示了一個似乎與筆劃寬度具有相同半徑的圓。

<div style="width: 100%; height: 100%;">
<svg width=100% height=500px>
<g class="sankey-layer">
<g class="link-group">
<path d="M107.61971830985915,30C107.61971830985915,74,107.61971830985915,74,107.61971830985915,118" fill="none" stroke="#000000" stroke-opacity="1" stroke-width="200"></path>
<path d="M251.11267605633802,30C251.11267605633802,192,328.943661971831,192,328.943661971831,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="71.74647887323944"></path>
<path d="M478.38028169014075,30C478.38028169014075,192,384.7464788732394,192,384.7464788732394,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="39.859154929577464"></path>
<path d="M542.1549295774647,30C542.1549295774647,192,572.1549295774648,192,572.1549295774648,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="87.69014084507042"></path>
<path d="M344.8169014084507,30C344.8169014084507,192,452.50704225352115,192,452.50704225352115,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="95.66197183098592"></path>
<path d="M143.49295774647888,148C143.49295774647888,251,153.49295774647888,251,153.49295774647888,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="79.71830985915493"></path>
<path d="M409.12773522289996,148C409.12773522289996,251,213.28169014084506,251,213.28169014084506,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="39.859154929577464"></path>
</g>
</g>
</svg>
</div>
任何線索來自哪里以及我可以做些什么來避免它?
澄清:
路徑由 d3 計算。它不是手動創建的圖形,我正在尋找問題的一般解決方案,而不是這個特定示例的解決方案。
uj5u.com熱心網友回復:
我將第一條路徑更改為<path d="M107.62,30L107.62,118" fill="none" stroke="#000000" stroke-opacity="1" stroke-width="200"></path>. 我通過將其加載到 Illustrator 中解決了這個問題。
我不是 100% 確定問題出在哪里,但也許比我更聰明的人會弄清楚。SVG 的數學傷害了我的大腦。
<div style="width: 100%; height: 100%;">
<svg width=100% height=500px>
<g class="sankey-layer">
<g class="link-group">
<path d="M107.62,30L107.62,118" fill="none" stroke="#000000" stroke-opacity="1" stroke-width="200"></path>
<path d="M251.11267605633802,30C251.11267605633802,192,328.943661971831,192,328.943661971831,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="71.74647887323944"></path>
<path d="M478.38028169014075,30C478.38028169014075,192,384.7464788732394,192,384.7464788732394,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="39.859154929577464"></path>
<path d="M542.1549295774647,30C542.1549295774647,192,572.1549295774648,192,572.1549295774648,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="87.69014084507042"></path>
<path d="M344.8169014084507,30C344.8169014084507,192,452.50704225352115,192,452.50704225352115,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="95.66197183098592"></path>
<path d="M143.49295774647888,148C143.49295774647888,251,153.49295774647888,251,153.49295774647888,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="79.71830985915493"></path>
<path d="M409.12773522289996,148C409.12773522289996,251,213.28169014084506,251,213.28169014084506,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="39.859154929577464"></path>
</g>
</g>
</svg>
</div>
uj5u.com熱心網友回復:
Apperently一個瀏覽器相關的錯誤,你應該報告。
作為“后處理”解決方法,您可以使用我曾經創建的這個助手將平坦曲線轉換為L命令。(基于
雖然博客文章關注的問題看起來略有不同,但我確信這與我遇到的問題完全相同。
從某種意義上說,我覺得這里的根本問題是對路徑元素的濫用。當線條短于筆觸寬度時,將填充設定為none并增加筆觸寬度以繪制線條似乎無法正常作業。
博客文章建議改為繪制自定義貝塞爾曲線。這消除了對 stroke 屬性的需要,而我們可以只使用普通填充。這對我來說是一個合適的解決方案。讓我們看一下代碼。
在這個問題之前,我并沒有真正研究過桑基圖的圖形方面。在嘗試理解博客文章中提出的解決方案時(我需要將代碼更改為垂直作業而不是水平作業),我努力完全繪制出坐標指的是什么。d3 檔案對此并沒有真正的幫助。這是我為自己制作的資訊圖:

博客文章中的代碼使用了稍微不同的坐標命名。我對此進行了調整,添加了一些評論并試圖簡化它。
function sankeyLinkPath(link) {
/**
* This function is a drop in replacement for d3.sankeyLinkHorizontal().
* Except any accessors/options.
*/
// 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;
let lsy1 = link.y0 link.width / 2;
let lty0 = link.y1 - link.width / 2;
let lty1 = link.y1 link.width / 2;
// 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();
}
它的作用是繪制鏈接輪廓的路徑。

這將我的代碼減少到:
<path
d={sankeyLinkPath(link)}
fill='#333'
/>
調整 Sankey 的垂直繪圖
最后,我將代碼調整為垂直作業而不是水平作業:
function sankeyLinkPath(link) {
/**
* This function is a drop in replacement for d3.sankeyLinkVertical().
* Except any accessors/options.
*/
// 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;
let lsx1 = link.y0 (link.width / 2) * linkWidth;
let ltx0 = link.y1 - (link.width / 2) * linkWidth;
let ltx1 = link.y1 (link.width / 2) * linkWidth;
// 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();
}
現在產生了這個絕對正常的桑基圖:
.opacity-40 {
opacity: 0.4;
}
<div width="100%" height="100%">
<svg width="648" height="384">
<g class="sankey-links">
<g class="sankey-link group">
<path
class="opacity-40 group-hover:opacity-80"
d="M11.370422535211262,40C11.370422535211262,77.83333333333334,11.370422535211262,77.83333333333334,11.370422535211262,115.66666666666667L216.03802816901413,115.66666666666667C216.03802816901413,77.83333333333334,216.03802816901413,77.83333333333334,216.03802816901413,40L11.370422535211262,40"
fill="#0011ff"
></path>
</g>
<g class="sankey-link group">
<path
class="opacity-40 group-hover:opacity-80"
d="M5.47464788732394,154.66666666666669C5.47464788732394,249.83333333333334,5.47464788732394,249.83333333333334,5.47464788732394,345L104.01830985915494,345C104.01830985915494,249.83333333333334,104.01830985915494,249.83333333333334,104.01830985915494,154.66666666666669L5.47464788732394,154.66666666666669"
fill="#00bbff"
></path>
</g>
<g class="sankey-link group">
<path
class="opacity-40 group-hover:opacity-80"
d="M318.26478873239444,40C318.26478873239444,192.5,312.9971830985916,192.5,312.9971830985916,345L403.9605633802817,345C403.9605633802817,192.5,409.22816901408453,192.5,409.22816901408453,40L318.26478873239444,40"
fill="#0011ff"
></path>
</g>
<g class="sankey-link group">
<path
class="opacity-40 group-hover:opacity-80"
d="M487.8718309859155,40C487.8718309859155,192.5,559.9845070422538,192.5,559.9845070422538,345L643.367605633803,345C643.367605633803,192.5,571.2549295774647,192.5,571.2549295774647,40L487.8718309859155,40"
fill="#00bbff"
></path>
</g>
<g class="sankey-link group">
<path
class="opacity-40 group-hover:opacity-80"
d="M113.70422535211267,154.66666666666669C113.70422535211267,249.83333333333334,123.70422535211273,249.83333333333334,123.70422535211273,345L199.50704225352118,345C199.50704225352118,249.83333333333334,189.50704225352112,249.83333333333334,189.50704225352112,154.66666666666669L113.70422535211267,154.66666666666669"
fill="#00bbff"
></path>
</g>
<g class="sankey-link group">
<path
class="opacity-40 group-hover:opacity-80"
d="M231.1985915492958,40C231.1985915492958,192.5,412.8042253521127,192.5,412.8042253521127,345L481.0267605633804,345C481.0267605633804,192.5,299.4211267605634,192.5,299.4211267605634,40L231.1985915492958,40"
fill="#0011ff"
></path>
</g>
<g class="sankey-link group">
<path
class="opacity-40 group-hover:opacity-80"
d="M417.22957746478875,40C417.22957746478875,77.83333333333334,413.3159790754746,77.83333333333334,413.3159790754746,115.66666666666667L466.37795090646057,115.66666666666667C466.37795090646057,77.83333333333334,470.2915492957747,77.83333333333334,470.2915492957747,40L417.22957746478875,40"
fill="#00bbff"
></path>
</g>
<g class="sankey-link group">
<path
class="opacity-40 group-hover:opacity-80"
d="M577.9929577464789,40C577.9929577464789,192.5,486.92253521126764,192.5,486.92253521126764,345L524.8239436619718,345C524.8239436619718,192.5,615.894366197183,192.5,615.894366197183,40L577.9929577464789,40"
fill="#0011ff"
></path>
</g>
<g class="sankey-link group">
<path
class="opacity-40 group-hover:opacity-80"
d="M412.4737255543479,154.66666666666669C412.4737255543479,249.83333333333334,205.82394366197187,249.83333333333334,205.82394366197187,345L243.72535211267612,345C243.72535211267612,249.83333333333334,450.37513400505213,249.83333333333334,450.37513400505213,154.66666666666669L412.4737255543479,154.66666666666669"
fill="#00bbff"
></path>
</g>
<g class="sankey-link group">
<path
class="opacity-40 group-hover:opacity-80"
d="M195.40281690140844,154.66666666666669C195.40281690140844,249.83333333333334,257.5154929577465,249.83333333333334,257.5154929577465,345L287.8366197183099,345C287.8366197183099,249.83333333333334,225.72394366197184,249.83333333333334,225.72394366197184,154.66666666666669L195.40281690140844,154.66666666666669"
fill="#00bbff"
></path>
</g>
<g class="sankey-link group">
<path
class="opacity-40 group-hover:opacity-80"
d="M453.32302132899576,154.66666666666669C453.32302132899576,192.5,457.2918698867473,192.5,457.2918698867473,230.33333333333334L472.452433267029,230.33333333333334C472.452433267029,192.5,468.48358470927747,192.5,468.48358470927747,154.66666666666669L453.32302132899576,154.66666666666669"
fill="#00bbff"
></path>
</g>
<g class="sankey-link group">
<path
class="opacity-40 group-hover:opacity-80"
d="M465.2932783374515,269.33333333333337C465.2932783374515,307.1666666666667,289.94225352112676,307.1666666666667,289.94225352112676,345L297.5225352112676,345C297.5225352112676,307.1666666666667,472.87356002759236,307.1666666666667,472.87356002759236,269.33333333333337L465.2932783374515,269.33333333333337"
fill="#00bbff"
></path>
</g>
<g class="sankey-link group">
<path
class="opacity-40 group-hover:opacity-80"
d="M456.8707431261839,269.33333333333337C456.8707431261839,307.1666666666667,537.3507042253524,307.1666666666667,537.3507042253524,345L544.9309859154931,345C544.9309859154931,307.1666666666667,464.4510248163248,307.1666666666667,464.4510248163248,269.33333333333337L456.8707431261839,269.33333333333337"
fill="#00bbff"
></path>
</g>
</g>
</svg>
</div>
我對使用 SVG 和 d3 有了一些了解。我希望該解決方案在未來對其他人有所幫助。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/489934.html
上一篇:SVG線性漸變不適用于其他元素
