Program Tip

SVG에서 속이 빈 원 그리기

programtip 2020. 11. 24. 19:24
반응형

SVG에서 속이 빈 원 그리기


SVG에서 빈 원을 그리는 방법을 잘 모르겠습니다.

색상으로 채워진 링 모양을 검은 색 윤곽선으로하고 싶습니다.

제가 생각했던 방식은 2 개의 원이 있는데 하나는 다른 하나보다 반경이 더 작습니다. 문제는 내가 그것들을 채울 때 어떻게 작은 원이 그 위에있는 것과 같은 채움 색상을 갖도록 만들 수 있습니까?


사용 fill="none"하면 stroke(윤곽선) 그려집니다.

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
   <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="none" />
</svg> 

또는 두 가지 색상을 원하는 경우 :

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
   <circle cx="100" cy="50" r="40" stroke="black" stroke-width="3" fill="none" />
   <circle cx="100" cy="50" r="39" stroke="red" stroke-width="2" fill="none" />
</svg>


Chasbeen 덕분에 SVG에서 진정한 링 / 도넛을 만드는 방법을 알아 냈습니다. 바깥 쪽 원은 실제로 닫혀 있지 않으며 스트로크를 사용할 때만 나타납니다. 동심원이 많은 경우, 특히 대화 형인 경우 (예 : CSS 호버 명령 사용) 매우 유용합니다.

그리기 명령의 경우 ...

M cx, cy // Move to center of ring
m 0, -outerRadius // Move to top of ring
a outerRadius, outerRadius, 0, 1, 0, 1, 0 // Draw outer arc, but don't close it
Z // default fill-rule:even-odd will help create the empty innards
m 0 outerRadius-innerRadius // Move to top point of inner radius
a innerRadius, innerRadius, 0, 1, 1, -1, 0 // Draw inner arc, but don't close it
Z // Close the inner ring. Actually will still work without, but inner ring will have one unit missing in stroke       

JSFiddle- 상호 작용을 시뮬레이션하기위한 여러 링과 CSS가 포함되어 있습니다. 시작점 (상단)에서 누락 된 단일 픽셀이 있다는 단점은 획을 추가 한 경우에만 존재합니다.

편집 :이 찾을 SO 답변을 (더 나은 아직, 이 답 ) 일반적으로 빈 내장을 얻을하는 방법을 설명합니다


MDragon00의 대답은 작동하지만 내부 및 외부 원이 완벽하게 정렬되지 않았습니다 (예 : 가운데).

정확히 정렬을 얻기 위해 4 개의 반원 호 (2 개의 바깥 쪽과 2 개의 안쪽 방향)를 사용하여 그의 접근 방식을 약간 수정했습니다.

<svg width="100" height="100">
  <path d="M 50 10 A 40 40 0 1 0 50 90 A 40 40 0 1 0 50 10 Z M 50 30 A 20 20 0 1 1 50 70 A 20 20 0 1 1 50 30 Z" fill="#0000dd" stroke="#00aaff" stroke-width="3" />
</svg>

<!--

Using this path definition as d:

M centerX (centerY-outerRadius)
A outerRadius outerRadius 0 1 0 centerX (centerY+outerRadius)
A outerRadius outerRadius 0 1 0 centerX (centerY-outerRadius)
Z
M centerX (centerY-innerRadius)
A innerRadius innerRadius 0 1 1 centerX (centerY+innerRadius)
A innerRadius innerRadius 0 1 1 centerX (centerY-innerRadius)
Z

-->


이것은 고전적인 도넛 모양입니다. SVG를 생성하는 표준 SVG 또는 JavaScript로이를 달성하려고하는지 확실하지 않습니다. 목표는 단일 경로 정의에 상대 "moveto"명령을 포함하여 달성 할 수 있습니다.

그리고 대화식 예제의 오른쪽에있는 "도넛 구멍"을 클릭합니다. 최소한 빨간 도넛을 만든 경로 정의를 볼 수 있습니다.


두 개의 구성 요소와 fill-rule = "evenodd"가있는 경로를 사용하여 SVG 사양에 따라이를 수행 할 수 있습니다. 두 구성 요소는 결합하여 원을 형성하는 반원 호입니다 (아래의 "d"속성에서 각각 'z'로 끝남). 안쪽 원 안의 영역은 모양의 일부로 간주되지 않으므로 상호 작용이 좋습니다.

아래를 조금 해독하기 위해 "340 260"은 외부 원의 상단 중앙, "290 290"은 외부 원의 반경 (2 회), "340 840"은 외부 원의 하단 중앙입니다. 에서 "340 492"는 내부 원의 상단 중앙, "58 58"은 내부 원의 반경 (2 회), "340 608"은 내부 원의 하단 중앙입니다.

<svg viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg">
    <path fill-rule="evenodd" d="M340 260A290 290 0 0 1 340 840A290 290 0 0 1 340 260zM340 492A58 58 0 0 1 340 608A58 58 0 0 1 340 492z" stroke-width="4" stroke="rgb(0,0,0)" fill="rgb(0,0,255)">
        <title>This will only display on the donut</title>
    </path>
</svg>

원에 확률이없는만큼 가까운 베 지어 호를 만드는 루틴이 있습니다. 완전한 원을 위해 경로에 4 개가 필요합니다.

 BezierCurve BezierArc(double ox, double oy, double r, double thetaa, double thetab)
    {
        double theta;
        double cpx[4];
        double cpy[4];
        int i;
        int sign = 1;

        while (thetaa > thetab)
            thetab += 2 * Pi;
        theta = thetab - thetaa;
        if (theta > Pi)
        {
            theta = 2 * Pi - theta;
            sign = -1;
        }
        cpx[0] = 1;
        cpy[0] = 0;
        cpx[1] = 1;
        cpy[1] = 4.0 / 3.0 * tan(theta / 4);
        cpx[2] = cos(theta) + cpy[1] * sin(theta);
        cpy[2] = sin(theta) - cpy[1] * cos(theta);
        cpx[3] = cos(theta);
        cpy[3] = sin(theta);
        cpy[1] *= sign;
        cpy[2] *= sign;
        cpy[3] *= sign;

        for (i = 0; i < 4; i++)
        {
            double xp = cpx[i] * cos(thetaa) + cpy[i] * -sin(thetaa);
            double yp = cpx[i] * sin(thetaa) + cpy[i] * cos(thetaa);
            cpx[i] = xp;
            cpy[i] = yp;
            cpx[i] *= r;
            cpy[i] *= r;
            cpx[i] += ox;
            cpy[i] += oy;
        }

        return BezierCurve({cpx[0], cpy[0]},{cpx[1], cpy[1]}, {cpx[2], cpy[2]}, {cpx[3], cpy[3]});
    }

참고 URL : https://stackoverflow.com/questions/8193675/draw-a-hollow-circle-in-svg

반응형