首页 > 解决方案 > 如何保持两条贝塞尔曲线之间的垂直宽度相等?

问题描述

我正在为桑基图创建带有贝塞尔曲线的点之间的链接。

这是我尝试过的代码:

let 
  margin = 10,
  x0 = 20,
  y0 = 20,
  x1 = 150,
  y1 = 100,
  width = 30,
  path = d3.path(),
  path2 = d3.path(),
  controlPointX = (x0 + x1) / 2;

/* with filled path */
path.moveTo(x0, y0);
path.bezierCurveTo(controlPointX, y0, controlPointX, y1, x1, y1);
path.lineTo(x1, y1 + width);
path.bezierCurveTo(controlPointX, y1 + width, controlPointX, y0 + width, x0, y0 + width);
path.closePath();

let svg = d3.select('svg');
let g = svg.append('g').attr('transform', `translate(${margin}, ${margin})`);
g.append('path')
  .attr('d', path)
  .attr('fill', 'red');

// curve 2 offset
y0 += 120;
y1 += 120;

// with stroke
path2.moveTo(x0, y0);
path2.bezierCurveTo(controlPointX, y0, controlPointX, y1, x1, y1);
g.append('path')
  .attr('d', path2)
  .attr('stroke-width', width)
  .attr('stroke', 'blue')
  .attr('fill', 'none');

在此处输入图像描述

在第一种方法中,两条曲线之间的垂直宽度不相同。但在第二个例子中,我使用了相同的单曲线和中风-高度,效果很好。我想通过填充路径实现相同的目标。

小提琴链接:https ://jsfiddle.net/3cxt40Lz/

标签: javascriptd3.jsmathsvg

解决方案


这是一个近似的解决方案。

我在矢量编辑软件中打开了生成的 SVG,以检查贝塞尔曲线的控制点。

在此处输入图像描述

玩了一下,结果发现将下控制点水平移动到左侧可以根据需要调整曲线:

在此处输入图像描述

所以回到代码,创建一个新的控制点向左移动width / 2

controlPointX2 = (x0 + x1 - width) / 2;

/* with filled path */
path.moveTo(x0, y0);
path.bezierCurveTo(controlPointX, y0, controlPointX, y1, x1, y1);
path.lineTo(x1, y1 + width);
path.bezierCurveTo(controlPointX2, y1 + width, controlPointX2, y0 + width, x0, y0 + width);

结果与蓝色曲线不完全一样,但非常接近,如下图所示,红色曲线显示在蓝色曲线上方(具有一定透明度)。

结果

更新了 jsFiddle:

https://jsfiddle.net/zbe90rjq/1/


推荐阅读