【问题标题】:Rounded corners in SVG path semi circleSVG路径半圆中的圆角
【发布时间】:2021-12-27 01:24:53
【问题描述】:

我有一条半圆形的路径。如何使角变圆?我不想使用stroke-linecap: round,因为我需要它只在这些角上被舍入:

<svg>
  <g>
    <!--background -->
    <path fill="none" stroke-dasharray="" stroke-width="16" stroke="#607985" d="M30 100 A 40 40 0 0 1 170 100"></path>
    <!-- strokes -->
    <path id="meter-back" fill="none" stroke-width="15" stroke="white" d="M30 100 A 40 40 0 0 1 170 100"></path>
    <!--progress -->
    <path id="meter-fill" fill="none" stroke-dashoffset="219.942" stroke-dasharray="109.971, 109.971" stroke="rgba(96,121,133,0.7)" stroke-width="15" d="M30 100 A 40 40 0 0 1 170 100" stroke="#607985"></path>

  </g>
</svg>

【问题讨论】:

  • 这能回答你的问题吗? SVG rounded corner
  • 您必须修改路径以在拐角处添加小弧线。根据@PeterO 链接中的一些答案。没有简单的方法。除了具有rx/ry 属性的&lt;rect&gt; 元素。
  • 谢谢@Peter,是的,我确实经历过,但我仍然无法让它工作

标签: javascript html css svg


【解决方案1】:

这是一个固定的解决方案。 dividerPos 可以在 0 到 1 的范围内:

const getPath = (outerRadius, innerRadius, cornerRadius, dividerPos) => {
  const angle = Math.PI * (1 - dividerPos);
  const outerPointX = outerRadius * Math.cos(angle);
  const outerPointY = outerRadius * -Math.sin(angle);
  const innerPointX = innerRadius * Math.cos(angle);
  const innerPointY = innerRadius * -Math.sin(angle);

  const left = `M ${-outerRadius},0 
    A ${outerRadius},${outerRadius} 0 0 1 
    ${outerPointX},${outerPointY}
    L ${innerPointX},${innerPointY}
    A ${innerRadius},${innerRadius} 0 0 0 ${-innerRadius},0       
    Q ${-innerRadius},${cornerRadius} 
    ${-innerRadius-cornerRadius},${cornerRadius} 
    H ${-outerRadius+cornerRadius}
    Q ${-outerRadius},${cornerRadius} 
    ${-outerRadius},0 
  Z`;
  
  const right = `M ${outerPointX},${outerPointY}
    A ${outerRadius},${outerRadius} 0 0 1 
    ${outerRadius},0
    Q ${outerRadius},${cornerRadius} 
    ${outerRadius-cornerRadius},${cornerRadius} 
    H ${innerRadius+cornerRadius}
    Q ${innerRadius},${cornerRadius} 
    ${innerRadius},0 
    A ${innerRadius},${innerRadius} 0 0 0 
    ${innerPointX},${innerPointY}       
  Z`;

  return {left, right};
};

const {left, right} = getPath(120, 90, 15, 0.5);
d3.select('.left').attr('d', left);
d3.select('.right').attr('d', right);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width='300' height='200'>
  <g transform='translate(150,150)'>
    <path stroke='grey' fill='grey' class='left'/>
    <path stroke='grey' fill='none' class='right'/>
  </g>
</svg>

【讨论】:

  • 感谢@Michael ? 就像魔术一样!
  • 但是为 dividerPos 传递的 1 并没有完全填满路径:getPath(120, 90, 15, 1);可以为此做些什么吗?
  • @Kshri 对于极端情况(0 和 1),您可以使用第一个解决方案
  • 对。非常感谢! ?
【解决方案2】:

使用getPath 例程计算所需路径 (半圆中心的0,0点):

const getPath = (outerRadius, innerRadius, cornerRadius) => {
  return `M ${-outerRadius},0 
    A ${outerRadius},${outerRadius} 1 1 1 ${outerRadius},0
    Q ${outerRadius},${cornerRadius} 
    ${outerRadius-cornerRadius},${cornerRadius} 
    H ${innerRadius+cornerRadius}
    Q ${innerRadius},${cornerRadius} 
    ${innerRadius},0 
    A ${innerRadius},${innerRadius} 0 0 0 
    ${-innerRadius},0       
    Q ${-innerRadius},${cornerRadius} 
    ${-innerRadius-cornerRadius},${cornerRadius} 
    H ${-outerRadius+cornerRadius}
    Q ${-outerRadius},${cornerRadius} 
    ${-outerRadius},0 
  Z`;
};

d3.select('path').attr('d', getPath(120, 90, 12));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

<svg width='300' height='200'>
  <g transform='translate(150,150)'>
    <path stroke='red' fill='none'/>
    <circle fill='red' r='5' cx='0' cy='0'/>
  </g>
</svg>

【讨论】:

  • 非常感谢! ?
  • 不幸的是,灰色图像中填充仪表的“stroke-dasharray”将不再起作用,因为路径现在只是一个轮廓
  • 那么,有没有办法只将半径点添加到现有路径?
  • @Kshri 我明白这个问题,打算尝试解决它...
  • 那将非常有帮助。非常感谢!