Home > Net >  Rounded corners in SVG path semi circle
Rounded corners in SVG path semi circle

Time:11-18

I have a path which is a semi-circle. How do I make the corners rounded? I do not want to use stroke-linecap: round as I need it to be rounded only on these corners: enter image description here

<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>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

Use getPath routine to compute the desired path (The 0,0 point in the center of the semi-circle):

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>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

Here is a fixed solution. dividerPos can be in range from 0 to 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>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related