SVG中的厚Bezier曲线没有伪影

时间:2015-12-14 12:01:19

标签: css d3.js svg

我尝试绘制粗Bezier lines(对于自定义Sankey diagram)。 我使用SVG Paths,贝塞尔曲线的形式为C x1 y1, x2 y2, x y。我使用stroke而不是fill,因此它们具有恒定的宽度(并且可以表示流)。

如果线很薄或垂直差异相对较小,它的效果非常好。然而,如果它们非常厚,我会得到一些令人讨厌的文物(看起来像角) - 请参见下图中的右下曲线:

enter image description here

来源:http://jsfiddle.net/stared/83jr5fub/

有没有办法避免伪影,即:

  • 确保x1左侧或x
  • 右侧没有任何内容
  • 左右实际宽度与stroke-width匹配?

2 个答案:

答案 0 :(得分:8)

我认为在你的情况下(使用给定的路径),他的最佳解决方案是关闭路径,并使用其填充属性。

要执行此操作,您必须在lineTo(0, strokeWidth)的末尾创建BezierCurveTo,然后以其他方式重绘bezierCurve:

var svg = d3.select("#chart");

var data = [
	{t: 5, dy: 10},
	{t: 5, dy: 20},
	{t: 5, dy: 40},
	{t: 20, dy: 10},
	{t: 20, dy: 20},
	{t: 20, dy: 40},
	{t: 50, dy: 10},
	{t: 50, dy: 20},
	{t: 50, dy: 40},
];

var ctrl = 10;
var dx = 40;
var spacing = 100;
var colors = d3.scale.category10();

svg
  .attr("width", 4 * spacing)
  .attr("height", 4 * spacing);

svg.selectAll("path")
  .data(data)
  .enter()
  	.append("path")
    .attr("d", function (d, i) {
      var x1 = spacing + spacing * (i % 3);
      var y1 = spacing + spacing * Math.floor(i / 3);
      return "M" + x1 + "," + y1 +
      "c" + ctrl + "," + 0 +
      " " + (dx - ctrl) + "," + d.dy +
      " " + dx + "," + d.dy +
      // move down for the wanted width
      "l" + (0) + "," + (d.t) +
      // negate all values
      "c" + (ctrl * -1) + "," + 0 +
      " " + ((dx - ctrl) * -1) + "," + (d.dy * -1) +
      " " + (dx * -1) + "," + (d.dy * -1);
  })
  .style("fill", colors(0))
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg id="chart"></svg>

由于这里的动画价值超过1万字,其中一个显示了正在发生的事情以及为什么它不能被称为浏览器错误:

@keyframes dash {
  from {
     stroke-dashoffset: -10%;
  }
   to {
     stroke-dashoffset: 90%;
  }
 }
@-webkit-keyframes dash {
  from {
     stroke-dashoffset: -10%;
  }
   to {
     stroke-dashoffset: 90%;
  }
 }
#dashed{
  animation : dash 12s linear infinite;
  }
<svg height="200" width="200" id="chart" viewBox="290 260 100 100">
<path id="dashed" style="fill: none; stroke: rgb(31, 119, 180); stroke-width: 50; stroke-dasharray: 3, 3;" d="M300,300c10,0 30,40 40,40"></path>
<path style="fill: none; stroke: black;" d="M300,300c10,0 30,40 40,40">
</path></svg>

答案 1 :(得分:1)

Kaiido给出了一个优秀而完整的答案,为什么显示粗行程宽度的SVG路径带有伪影以及如何避免这种情况。我将尝试提供一些特定于D3.js Sankey图表的信息,因为我最近遇到了与Piotr Migdal相同的问题。

原始Sankey图代码

(来自this Sankey example中的Sankey.js,类似于Piotr Migdal提到的例子)

{{1}}

修改后的代码

{{1}}

然后你还需要改变你的CSS:

  • stroke:none
  • 设置填充颜色

并删除任何设置HTML元素笔触宽度的D3代码。