如何将svg中的贝塞尔曲线转为正弦曲线?

Swa*_*ain 2 html svg bezier vector-graphics reactjs

在此输入图像描述

我一直在尝试在 svg 中制作这个形状。问题是,我想用蓝色手柄来操纵它。我已经制作了一个简单的箭头,并且能够使用二次贝塞尔曲线改变其形状。但我不知道如何做这种形状。有什么方法可以将线条转换成这种弯曲的形式吗?

AKX*_*AKX 5

您可以使用getPointAtLengthgetTotalLengthAPI 沿着任何任意 SVG 几何体“骑行”,并生成正弦波。

这是一个纯 TypeScript 的示例(在这里找到一个带有一些额外功能的交互式 React CodeSandbox)。

function computeWave(
  path: SVGPathElement,
  freq: number,
  maxAmp: number,
  phase: number,
  res: number
) {
  // Get the points of the geometry with the given resolution
  const length = path.getTotalLength();
  const points = [];
  if (res < 0.1) res = 0.1; // prevent infinite loop
  for (let i = 0; i <= length + res; i += res) {
    const { x, y } = path.getPointAtLength(i);
    points.push([x, y]);
  }
  // For each of those points, generate a new point...
  const sinePoints = [];
  for (let i = 0; i < points.length - 1; i++) {
    // Numerical computation of the angle between this and the next point
    const [x0, y0] = points[i];
    const [x1, y1] = points[i + 1];
    const ang = Math.atan2(y1 - y0, x1 - x0);
    // Turn that 90 degrees for the normal angle (pointing "left" as far
    // as the geometry is considered):
    const normalAngle = ang - Math.PI / 2;
    // Compute the sine-wave phase at this point.
    const pointPhase = ((i / (points.length - 1)) * freq - phase) * Math.PI * 2;
    // Compute the sine-wave amplitude at this point.
    const amp = Math.sin(pointPhase) * maxAmp;
    // Apply that to the current point.
    const x = x0 + Math.cos(normalAngle) * amp;
    const y = y0 + Math.sin(normalAngle) * amp;
    sinePoints.push([x, y]);
  }
  // Terminate the sine points where the shape ends.
  sinePoints.push(points[points.length - 1]);
  // Compute SVG polyline string.
  return sinePoints
    .map(([x, y], i) => `${i === 0 ? "M" : "L"}${x},${y}`)
    .join(" ");
}
Run Code Online (Sandbox Code Playgroud)

它在橙色线之后生成蓝色线(描述为M100,100 C150,100,150,250,200,200): 在此输入图像描述

当然,您可以对此进行调整,例如在末端“捏住”波,以避免任意相位的任何突然结束等。