画一条“波浪线"在 SVG 中 [英] Draw a "squiggly line" in SVG

查看:66
本文介绍了画一条“波浪线"在 SVG 中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究如何在任意 SVG path 元素上绘制波浪线.该路径由 React 组件生成.例如,我试图在这个问题中复制 这一行:

I'm trying to work out how to draw a squiggly line on an arbitrary SVG path element. The path is generated by a React Component. For example, I'm trying to replicate the line in this question:

在 SVG 和/或 JavaScript 生成的路径中是否有一种简单的方法可以做到这一点?

Is there an easy way to do this in SVG and/or JavaScript generated paths?

我考虑过使用 s 路径命令连接一系列曲线,但随后我需要计算沿曲线的点.我也考虑过某种置换过滤器,但我不确定从哪里开始.

I've considered joining up a series of curves using the s path command, but then I would need to calculate points along the curve. I've also considered some sort of displacement filter but I'm not really sure where to start.

推荐答案

在我看来,最简单的方法就是循序渐进.然后,在每一步中,插入一条二次贝塞尔曲线,其控制点位于两条曲线的中间并垂直于曲线.然后下一步切换控制点所在的一侧.

Seems to me the easiest way would be step along the path. Then, at each step, insert a quadratic bezier curve with a control point that is half way between them and perpendicular to the curve. Then for the next step switch the side that the control point is on.

function makeSquiggle(squigglePathId, followPathId, squiggleStep, squiggleAmplitude)
{
  var followPath = document.getElementById(followPathId);
  var pathLen = followPath.getTotalLength();

  // Adjust step so that there are a whole number of steps along the path
  var numSteps = Math.round(pathLen / squiggleStep);

  var pos = followPath.getPointAtLength(0);
  var newPath = "M" + [pos.x, pos.y].join(',');
  var side = -1;
  for (var i=1; i<=numSteps; i++)
  {
    var last = pos;
    var pos = followPath.getPointAtLength(i * pathLen / numSteps);

    // Find a point halfway between last and pos. Then find the point that is
    // perpendicular to that line segment, and is squiggleAmplitude away from
    // it on the side of the line designated by 'side' (-1 or +1).
    // This point will be the control point of the quadratic curve forming the
    // squiggle step.
    
    // The vector from the last point to this one
    var vector = {x: (pos.x - last.x),
                  y: (pos.y - last.y)};
    // The length of this vector
    var vectorLen = Math.sqrt(vector.x * vector.x + vector.y * vector.y);
    // The point halfwasy between last point and tis one
    var half = {x: (last.x + vector.x/2),
                y: (last.y + vector.y/2)};
    // The vector that is perpendicular to 'vector'
    var perpVector = {x: -(squiggleAmplitude * vector.y / vectorLen),
                      y: (squiggleAmplitude * vector.x / vectorLen)};
    // No calculate the control point position
    var controlPoint = {x: (half.x + perpVector.x * side),
                        y: (half.y + perpVector.y * side)};
    newPath += ("Q" + [controlPoint.x, controlPoint.y, pos.x, pos.y].join(','));
    // Switch the side (for next step)
    side = -side;
  }
  var squigglePath = document.getElementById(squigglePathId);
  squigglePath.setAttribute("d", newPath);
}


makeSquiggle("squiggle", "follow", 25, 20);

#follow {
  fill: none;
  stroke: grey;
  stroke-width: 2;
}

#squiggle {
  fill: none;
  stroke: red;
  stroke-width: 2;
}

<svg width="500" height="400">
  <path id="follow" d="M 50,300 C 100,100 300,0, 350,250 L 450,200"/>
  <path id="squiggle" d="M0,0"/>
</svg>

这篇关于画一条“波浪线"在 SVG 中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆