SVG 둥근 모서리


84

다음 SVG가 있습니다.

<svg>
  <g>
    <path id="k9ffd8001" d="M64.5 45.5 82.5 45.5 82.5 64.5 64.5 64.5 z" stroke="#808600" stroke-width="0" transform="rotate(0 0 0)" stroke-linecap="square" stroke-linejoin="round" fill-opacity="1" stroke-opacity="1" fill="#a0a700"></path>
    <path id="kb8000001" d="M64.5 45.5 82.5 45.5 82.5 64.5 64.5 64.5 z" stroke="#808600" stroke-width="0" transform="rotate(0 0 0)" stroke-linecap="square" stroke-linejoin="round" fill-opacity="1" stroke-opacity="1" fill="url(#k9ffb0001)"></path>
  </g>
</svg>

나는 CSS와 같은 싶어 border-top-right-radius하고 border-top-bottom-radius효과를.

둥근 모서리 효과를 어떻게 얻을 수 있습니까?


CSS border-radius와 그 변형이 SVG에서 작동하지 않는다는 것은 너무 나쁩니다 .
Steven Vachon

8
BTW. 직사각형이있는 경우 모서리를 추가 rx=3하거나 ry=3둥글게 할 수 있습니다. developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx
Lukas Liesis

답변:


126

SVG 경로를 사용하여 둥근 사각형을 만드는 방법은 다음과 같습니다.

<path d="M100,100 h200 a20,20 0 0 1 20,20 v200 a20,20 0 0 1 -20,20 h-200 a20,20 0 0 1 -20,-20 v-200 a20,20 0 0 1 20,-20 z" />

설명

m100,100 : point (100,100)로 이동

h200 : 현재 위치에서 200px 수평선을 그립니다.

a20,200 0 1 20,20 : X 및 Y 축에서 20px 차이가있는 지점에 시계 방향으로 20px X 반경, 20px Y 반경을 갖는 호를 그립니다.

v200 : 현재 위치에서 200px 수직선을 그립니다.

a20,2000-1-20,20 : X와 Y 반경이 20px 인 호를 시계 방향으로 X에서 -20px 차이가 있고 Y 축에서 20px 차이가 나는 지점에 그립니다.

h-200 : 현재 위치에서 -200px 수평선을 그립니다.

a20,2000-1-20, -20 : X 및 Y 반경이 20px 인 호를 시계 방향으로 X 축에서 -20px 차이가있는 점과 Y 축에서 -20px 차이가있는 지점까지 그립니다.

v-200 : 현재 위치에서 -200px 수직선을 그립니다.

a20,20 0 0 1 20, -20 : X와 Y 반경이 20px 인 호를 시계 방향으로 X에서 20px 차이가 있고 Y 축에서 -20px 차이가있는 지점까지 그립니다.

z : 경로 닫기

<svg width="440" height="440">
  <path d="M100,100 h200 a20,20 0 0 1 20,20 v200 a20,20 0 0 1 -20,20 h-200 a20,20 0 0 1 -20,-20 v-200 a20,20 0 0 1 20,-20 z" fill="none" stroke="black" stroke-width="3" />
</svg>


3
아크에 대한 자세한 내용에 관심이있는 사람은 다음 API를 참조하십시오. A rx ry x-axis-rotation large-arc-flag sweep-flag x y( developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths )
Nic Scozzaro

더 복잡한 모양이 아닌 둥근 사각형을 원하고 (인터넷 검색 중에 찾은 방법) 더 간단한 방법은 <svg viewBox="0 0 110 110" xmlns="http://www.w3.org/2000/svg"> `<rect x = "5"y = "5"width = "100"height를 사용하는 것입니다. = "100"rx = "15"style = "stroke : # 000000; fill : #FFFFFF"/>`</svg>
John Sibly

58

아무도 실제 SVG 답변을 게시하지 않은 이유를 모르겠습니다. 다음은 상단에 둥근 모서리 (반지름 3)가있는 SVG 사각형입니다.

<svg:path d="M0,0 L0,27 A3,3 0 0,0 3,30 L7,30 A3,3 0 0,0 10,27 L10,0 Z" />

이것은 Move To (M), Line To (L), Arc To (A), Line To (L), Arc To (A), Line To (L), Close Path (Z)입니다.

쉼표로 구분 된 숫자는 절대 좌표입니다. 호는 반지름과 호 유형을 지정하는 추가 매개 변수로 정의됩니다. 이것은 또한 상대 좌표를 사용하여 수행 할 수 있습니다 (L 및 A에 소문자 사용).

이러한 명령에 대한 전체 참조는 W3C SVG 경로 페이지에 있으며 SVG 경로에 대한 추가 참조 자료는 이 문서 에서 찾을 수 있습니다 .


12
이것은 내가 찾던 답이 아니라 유용하지 않다면 좋은 신이다. 항상 편지가 무엇인지 궁금했습니다.
Alex McCabe

1
설명에 대한 고맙습니다 :)
Osman Erdi

47

Applying rounded corners to paths / polygons에 대한 내 답변에서 언급했듯이 SVG 경로의 일반적으로 둥근 모서리에 대한 자바 스크립트 루틴을 http://plnkr.co/edit/kGnGGyoOCKil02k04snu 와 함께 작성했습니다 .

그것은 당신이 가질 수있는 뇌졸중 효과와 독립적으로 작동합니다. 사용하려면 Plnkr의 rounding.js 파일을 포함하고 다음과 같이 함수를 호출합니다.

roundPathCorners(pathString, radius, useFractionalRadius)

결과는 둥근 경로가됩니다.

결과는 다음과 같습니다.

SVG 경로 반올림 예


좋지만 상대 명령에 대한 지원이 더 좋을 것입니다.
Joachim Breitner 2015 년

1
나는 동의한다 :) 이것은 완전한 도서관에서의 시도가 아니라 내 문제를 해결하기위한 약간의 일회성이었다. 그 기능을 가진 포크를 환영합니다!
Yona Appletree 2015 년

이것에 대한 저장소가 있습니까? 제작 해주셔서 감사합니다.
Djave

1
나는 그것을 위해 repo를 만드는 것을 결코 귀찮게하지 않았습니다.
Yona Appletree

리포지토리에 대한 @Djave의 질문으로 돌아가고 싶습니다;-]
t3chb0t

37

당신은 명시 적으로 설정 한 stroke-linejoin할 수 round있지만이 stroke-width하기 0때문에, 물론 당신이 라운드에 획이없는 경우 둥근 모서리를 참조하지 않을거야.

다음은 획을 통해 둥근 모서리가있는 수정 된 예입니다.
http://jsfiddle.net/8uxqK/1/

<path d="M64.5 45.5 82.5 45.5 82.5 64.5 64.5 64.5 z"
      stroke-width="5"
      stroke-linejoin="round"
      stroke="#808600"
      fill="#a0a700" />

그렇지 않으면 (둥근 지방 스트로크가 아닌 실제 둥근 모양 채우기가 필요한 경우) @Jlange가 말한대로 실제 둥근 모양을 만들어야합니다.


jsfiddle에서 올바르게 표시되지만 로컬 HTML 문서에 복사 할 때 일반 사각형입니다.
Mads Skjern 2015 년

6
stroke-linecap대신 사용할 수 있습니다 stroke-linejoin. 그것은 나를 위해 작동합니다.
lobodart 2015

32

나는 또한 및 속성 <rect>을 제공 하는 평범한 오래된 것을 사용하는 것을 고려할 것입니다rxry

MDN SVG 문서 <-두 번째로 그려진 rect 요소에 유의하십시오.


2
그러나 OP는 모서리의 일부만 둥글게하기를 원합니다.
Robert Longson 2014 년

9
이것은 내 질문에 대한 대답이며, 이것이 나를이 페이지로 가져 왔습니다. 감사합니다!
스티븐 바샹

1
사각형뿐만 아니라 일부 요소 그룹에 둥근 모서리를 사용해야하는 경우 여기에서 볼 수있는 것처럼 clipPath developer.mozilla.org/pt-BR/docs/Web/SVG/Element/clipPath 를 사용하여 수행 할 수 있습니다. jsfiddle.net/thiagomata/mp28rnj6/1
Thiago Mata

OP의 데드 링크. :(
posfan12 dec.

@ posfan12는 고정이 :) 당신을 위해
여호수아

12

나는 오늘이 문제를 직접 겪었고 작은 JavaScript 함수를 작성하여 해결했습니다.

내가 말할 수있는 건,이 쉬운 SVG의 경로 요소를 제공하는 방법 모서리 둥근 없다 제외한 경우에만 (CSS)의 속성이 경우, 테두리를 둥글게해야하는 경우를 stroke, stroke-width그리고 대부분의 중요한 stroke-linejoin="round"완벽하게 충분하다.

그러나 필자의 경우 경로 개체를 사용 하여 다음과 같이 특정 색상으로 채워지고 테두리가 표시되지 않는 n 개의 모서리가있는 사용자 지정 모양을 만들었습니다 .

여기에 이미지 설명 입력

SVG 경로에 대한 좌표 배열을 취하고 완료된 경로 문자열을 반환 d하여 경로 html 요소 의 속성에 넣는 빠른 함수를 작성했습니다 . 결과 모양은 다음과 같습니다.

여기에 이미지 설명 입력

기능은 다음과 같습니다.

/**
 * Creates a coordinate path for the Path SVG element with rounded corners
 * @param pathCoords - An array of coordinates in the form [{x: Number, y: Number}, ...]
 */
function createRoundedPathString(pathCoords) {
    const path = [];
    const curveRadius = 3;

    // Reset indexes, so there are no gaps
    pathCoords = pathCoords.slice();

    for (let i = 0; i < pathCoords.length; i++) {

      // 1. Get current coord and the next two (startpoint, cornerpoint, endpoint) to calculate rounded curve
      const c2Index = ((i + 1) > pathCoords.length - 1) ? (i + 1) % pathCoords.length : i + 1;
      const c3Index = ((i + 2) > pathCoords.length - 1) ? (i + 2) % pathCoords.length : i + 2;

      const c1 = pathCoords[i];
      const c2 = pathCoords[c2Index],
      const c3 = pathCoords[c3Index];

      // 2. For each 3 coords, enter two new path commands: Line to start of curve, bezier curve around corner.

      // Calculate curvePoint c1 -> c2
      const c1c2Distance = Math.sqrt(Math.pow(c1.x - c2.x, 2) + Math.pow(c1.y - c2.y, 2));
      const c1c2DistanceRatio = (c1c2Distance - curveRadius) / c1c2Distance;
      const c1c2CurvePoint = [
        ((1 - c1c2DistanceRatio) * c1.x + c1c2DistanceRatio * c2.x).toFixed(1),
        ((1 - c1c2DistanceRatio) * c1.y + c1c2DistanceRatio * c2.y).toFixed(1)
      ];

      // Calculate curvePoint c2 -> c3
      const c2c3Distance = Math.sqrt(Math.pow(c2.x - c3.x, 2) + Math.pow(c2.y - c3.y, 2));
      const c2c3DistanceRatio = curveRadius / c2c3Distance;
      const c2c3CurvePoint = [
        ((1 - c2c3DistanceRatio) * c2.x + c2c3DistanceRatio * c3.x).toFixed(1),
        ((1 - c2c3DistanceRatio) * c2.y + c2c3DistanceRatio * c3.y).toFixed(1)
      ];

      // If at last coord of polygon, also save that as starting point
      if (i === pathCoords.length - 1) {
        path.unshift('M' + c2c3CurvePoint.join(','));
      }

      // Line to start of curve (L endcoord)
      path.push('L' + c1c2CurvePoint.join(','));
      // Bezier line around curve (Q controlcoord endcoord)
      path.push('Q' + c2.x + ',' + c2.y + ',' + c2c3CurvePoint.join(','));
    }
    // Logically connect path to starting point again (shouldn't be necessary as path ends there anyway, but seems cleaner)
    path.push('Z');

    return path.join(' ');
}

상단에 curveRadius 변수를 설정하여 반올림 강도를 결정할 수 있습니다 . 100x100 (뷰포트) 좌표계의 경우 기본값은 3이지만 SVG 크기에 따라이를 조정해야 할 수도 있습니다.


1
이 수학은 굉장합니다. 나는 그것을 이해하고 다각형이 둥근 모서리를 갖도록 안드로이드에서 구현했습니다.
Adil Soomro

1
이것이 바로 내가 StackOverflow를 좋아하는 이유입니다.
Bangkokian

5

이 질문은 인터넷 검색 "svg rounded corners path"에 대한 첫 번째 결과입니다. 사용에 대한 Phrogz 제안 stroke에는 몇 가지 제한 사항이 있습니다 (즉, 다른 용도로 스트로크를 사용할 수 없으며 스트로크 너비에 맞게 치수를 수정해야 함).

곡선을 사용하는 Jlange 제안이 더 좋지만 구체적이지 않습니다. 둥근 모서리를 그리기 위해 2 차 베 지어 곡선을 사용했습니다. 인접한 가장자리에 파란색 점과 두 개의 빨간색 점으로 표시된 모서리 그림을 고려하십시오.

인접한 모서리에 두 점이있는 파란색으로 표시된 그림의 모서리

두 줄은 L명령 으로 만들 수 있습니다 . 이 날카로운 모서리를 둥근 모서리로 바꾸려면 왼쪽 빨간색 점에서 곡선 그리기를 시작합니다 (사용 M x,y하여 해당 점으로 이동). 이제 2 차 베 지어 곡선에는 파란색 점에 설정해야하는 단일 제어점이 있습니다. 곡선의 끝을 오른쪽 빨간색 점에 설정합니다. 두 빨간색 점의 접선이 이전 선의 방향이므로 "둥근 모서리"라는 유창한 전환을 볼 수 있습니다.

이제 둥근 모서리 이후의 모양을 계속하려면 두 모서리 사이의 선 사이에 제어점을 설정하여 베 지어 곡선의 직선을 얻을 수 있습니다.

경로를 결정하는 데 도움이되도록 가장자리와 반경을 허용하는이 Python 스크립트를 작성했습니다. 벡터 수학은 실제로 이것을 매우 쉽게 만듭니다. 출력 결과 이미지 :

스크립트 출력에서 ​​생성 된 모양

#!/usr/bin/env python
# Given some vectors and a border-radius, output a SVG path with rounded
# corners.
#
# Copyright (C) Peter Wu <peter@lekensteyn.nl>

from math import sqrt

class Vector(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def sub(self, vec):
        return Vector(self.x - vec.x, self.y - vec.y)

    def add(self, vec):
        return Vector(self.x + vec.x, self.y + vec.y)

    def scale(self, n):
        return Vector(self.x * n, self.y * n)

    def length(self):
        return sqrt(self.x**2 + self.y**2)

    def normal(self):
        length = self.length()
        return Vector(self.x / length, self.y / length)

    def __str__(self):
        x = round(self.x, 2)
        y = round(self.y, 2)
        return '{},{}'.format(x, y)

# A line from vec_from to vec_to
def line(vec_from, vec_to):
    half_vec = vec_from.add(vec_to.sub(vec_from).scale(.5))
    return '{} {}'.format(half_vec, vec_to)

# Adds 'n' units to vec_from pointing in direction vec_to
def vecDir(vec_from, vec_to, n):
    return vec_from.add(vec_to.sub(vec_from).normal().scale(n))

# Draws a line, but skips 'r' units from the begin and end
def lineR(vec_from, vec_to, r):
    vec = vec_to.sub(vec_from).normal().scale(r)
    return line(vec_from.add(vec), vec_to.sub(vec))

# An edge in vec_from, to vec_to with radius r
def edge(vec_from, vec_to, r):
    v = vecDir(vec_from, vec_to, r)
    return '{} {}'.format(vec_from, v)


# Hard-coded border-radius and vectors
r = 5
a = Vector(  0,  60)
b = Vector(100,   0)
c = Vector(100, 200)
d = Vector(  0, 200 - 60)

path = []
# Start below top-left edge
path.append('M {} Q'.format(a.add(Vector(0, r))))

# top-left edge...
path.append(edge(a, b, r))
path.append(lineR(a, b, r))
path.append(edge(b, c, r))
path.append(lineR(b, c, r))
path.append(edge(c, d, r))
path.append(lineR(c, d, r))
path.append(edge(d, a, r))
path.append(lineR(d, a, r))

# Show results that can be pushed into a <path d="..." />
for part in path:
    print(part)

3

다음은 탭 경로입니다.

https://codepen.io/mochime/pen/VxxzMW

<!-- left tab -->
<div>
  <svg width="60" height="60">
    <path d="M10,10 
             a10 10 0 0 1 10 -10
             h 50   
             v 47
             h -50
             a10 10 0 0 1 -10 -10
             z"
      fill="#ff3600"></path>
  </svg>
</div>

<!-- right tab -->
<div>
  <svg width="60" height="60">
    <path d="M10 0   
             h 40
             a10 10 0 0 1 10 10
             v 27
             a10 10 0 0 1 -10 10
             h -40
             z"
      fill="#ff3600"></path>
  </svg>
</div>

<!-- tab tab :) -->
<div>
  <svg width="60" height="60">
    <path d="M10,40 
             v -30
             a10 10 0 0 1 10 -10
             h 30
             a10 10 0 0 1 10 10
             v 30
             z"
      fill="#ff3600"></path>
  </svg>
</div>

다른 답변은 역학을 설명했습니다. 특히 hossein-maktoobian의 답변이 마음에 들었습니다.

펜의 경로는 작업을 방해하며 값은 원하는 치수에 맞게 수정할 수 있습니다.


1

나는 해결책을 찾았지만 약간 해키 이므로 항상 작동하지 않을 수 있습니다. 정말 작은 값을 가진 호 (A 또는 a)가있는 경우 한 지점에 곡선을 생성하여 둥근 모서리를 형성하도록 강요합니다.

<svg viewBox="0 0 1 0.6" stroke="black" fill="grey" style="stroke-width:0.05px;">
  <path d="M0.7 0.2 L0.1 0.1 A0.0001 0.0001 0 0 0 0.099 0.101 L0.5 0.5Z"></path>
</svg>


1

@ hmak.me의 답변 구현을 단순화하기 위해 여기에 둥근 사각형을 생성하는 주석이 달린 React 코드가 있습니다.

const Rect = ({width, height, round, strokeWidth}) => {
    // overhang over given width and height that we get due to stroke width
    const s = strokeWidth / 2;

    // how many pixels do we need to cut from vertical and horizontal parts
    // due to rounded corners and stroke width
    const over = 2 * round + strokeWidth;

    // lengths of straight lines
    const w = width - over;
    const h = height - over;

    // beware that extra spaces will not be minified
    // they are added for clarity
    const d = `
        M${round + s},${s}
        h${w}
        a${round},${round} 0 0 1 ${round},${round}
        v${h}
        a${round},${round} 0 0 1 -${round},${round}
        h-${w}
        a${round},${round} 0 0 1 -${round},-${round}
        v-${h}
        a${round},${round} 0 0 1 ${round},-${round}
        z
    `;
    return (
        <svg width={width} height={height}>
            <path d={d} fill="none" stroke="black" strokeWidth={strokeWidth} />
        </svg>
    );
};

ReactDOM.render(
    <Rect width={64} height={32} strokeWidth={2} round={4} />,
    document.querySelector('#app'),
);

Jsfiddle 링크.


-2
<?php
$radius = 20;
$thichness = 4;
$size = 200;

if($s == 'circle'){
  echo '<svg width="' . $size . '" height="' . $size . '">';
  echo '<circle cx="' . ($size/2) . '" cy="' . ($size/2) . '" r="' . (($size/2)-$thichness) . '" stroke="black" stroke-width="' . $thichness . '" fill="none" />';
  echo '</svg>';
}elseif($s == 'square'){
  echo '<svg width="' . $size . '" height="' . $size . '">';
  echo '<path d="M' . ($radius+$thichness) . ',' . ($thichness) . ' h' . ($size-($radius*2)-($thichness*2)) . ' a' . $radius . ',' . $radius . ' 0 0 1 ' . $radius . ',' . $radius . ' v' . ($size-($radius*2)-($thichness*2)) . ' a' . $radius . ',' . $radius . ' 0 0 1 -' . $radius . ',' . $radius . ' h-' . ($size-($radius*2)-($thichness*2)) . ' a' . $radius . ',' . $radius . ' 0 0 1 -' . $radius . ',-' . $radius . ' v-' . ($size-($radius*2)-($thichness*2)) . ' a' . $radius . ',' . $radius . ' 0 0 1 ' . $radius . ',-' . $radius . ' z" fill="none" stroke="black" stroke-width="' . $thichness . '" />';
  echo '</svg>';
}
?>

-5

경로 요소를 사용하고 있는데 경로에 곡선을 지정하지 않는 이유는 무엇입니까? 경로 요소를 사용하여 곡선을 만드는 방법은 여기를 참조하십시오. http://www.w3.org/TR/SVG/paths.html#PathDataCurveCommands


답변 해 주셔서 감사합니다. 정말 도움이되지만 문제는 KendoUI 차트를 사용하고 경로가 동적으로 생성된다는 것입니다. Phrogz를 제공하는 방법으로 변경하려고 시도했지만 border-radius = 10px 효과를 얻었지만 border-top-이 필요합니다. left-radius = 10px 및 border-bottom-left-radius = 10px 전용입니다. 나는 SVG에서 정말 새로운 것이기 때문에 두 번째 방법은 나에게 적합하지 않습니다. 그래서 당신은 나를 위해 경로 좌표를 쓸 수 있습니다. 미리 감사드립니다
Danis

제가 여러분을 위해이 작업을하고 싶은만큼 수학 / 좌표 위치를 살펴볼 시간이 없습니다. 링크에서 타원형 호 명령을 사용하는 것이 너무 어렵지 않아야합니다.
RestingRobot 2012
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.