javascript - 如何保持两条贝塞尔曲线之间的垂直宽度相等?
问题描述
我正在为桑基图创建带有贝塞尔曲线的点之间的链接。
这是我尝试过的代码:
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');
在第一种方法中,两条曲线之间的垂直宽度不相同。但在第二个例子中,我使用了相同的单曲线和中风-高度,效果很好。我想通过填充路径实现相同的目标。
解决方案
这是一个近似的解决方案。
我在矢量编辑软件中打开了生成的 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:
推荐阅读
- angular - 更新 Angular 时出现的 Ionic 5/电容器白屏
- validation - 如何创建 joi 模式来验证对象的对象
- c# - CLI 'dotnet new classlib' 命令不支持 .NET 5 特定于操作系统的 TFM
- python - OSMNX 找不到保存的 json 文件
- python - 如何在 PyCharm 中找出 BeautifulSoup 的系统依赖关系?
- tensorflow - 如何在 TF-Agents 框架中提取 DQN 代理的权重?
- angular - 如何检测 Angular Material Tabs 中的滚动事件以及如何以编程方式滚动回顶部?
- android - Android - 追踪应用使用如此多数据的原因
- python - 如何为 Tkinter 标签加载 .ttf 字体文件?
- asp.net-core - ASP.Net Core API 从 SSIS 给出 503 错误