如何使用 svg 路径创建时髦的圆圈?

How to create funky circle using svg path?

我正在尝试复制 Patrick Heng (patrickheng.com) 在他的网站上所做的事情。当您将鼠标悬停在固定的圆圈上时,我想创建这种时髦的效果。我最接近的是使用路径创建圆然后更改路径值,但这会产生非常糟糕的结果并且不受控制。

<path 
      d="
        M 25, 50
        a 25,25 0 1,1 50,0
        a 25,25 0 1,1 -50,0
        " />

我们可以更改 Ma 的值。

这里有一些与 二次贝塞尔曲线 路径类似的东西:

const angleFromCenter = (cx, cy, mx, my) => {
  const mAngle = Math.atan2(mx - cx, - my + cy);
  return mAngle > 0 ? mAngle : (Math.PI * 2 + mAngle);
};

const circlePath = (cx, cy, r, mx, my) => {
  const dist = Math.hypot(mx - cx, my - cy);
  let path = '';
  if (dist > r) {
    const angle = angleFromCenter(cx, cy, mx, my);
    const delta = Math.acos(r / dist); 
  
    const p0x = cx + r * Math.sin(angle - delta);
    const p0y = cy - r * Math.cos(angle - delta);
    const p2x = cx + r * Math.sin(angle + delta);
    const p2y = cy - r * Math.cos(angle + delta);
    const anchorR = dist > r * 2 ? r * 4 - dist : dist;
    const p1x = cx + anchorR * Math.sin(angle);
    const p1y = cy - anchorR * Math.cos(angle);
    path = `M ${p0x},${p0y} Q ${p1x},${p1y} ${p2x},${p2y}`;
  }
  return path + `M ${cx},${cy - r} A ${r},${r} 1 1 1 ${cx},${cy + r} A ${r},${r} 1 1 1 ${cx},${cy - r} Z`;
}

const svg = d3.select('svg')
const path = circlePath(100, 100, 50, 100, 100);
const circle = svg.append('path')
  .attr('d', path)
  .style('fill', 'blue');

svg.on('mousemove', (e) => {
  const d = circlePath(100, 100, 50, e.offsetX, e.offsetY);
  circle.attr('d', d);
});
  
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>

<svg width="200" height="200">
</svg>