SVG의 획 너비를 그리는 방법을 제어 할 수 있습니까?


204

현재 브라우저 기반 SVG 응용 프로그램을 구축 중입니다. 이 응용 프로그램 내에서 사각형을 포함하여 다양한 모양을 사용자가 스타일을 지정하고 배치 할 수 있습니다.

나는를 적용하면 stroke-widthSVG의에 rect말의 요소 1px, 스트로크가 적용됩니다 rect의 오프셋 및 다른 브라우저로 다른 방법으로 삽입. 특히 사각형의 바깥 쪽 너비와 시각적 위치를 계산하고 다른 요소 옆에 배치하려고 할 때 문제가되는 것으로 입증되었습니다 .

예를 들면 다음과 같습니다.

  • Firefox는 1px 삽입 (아래와 왼쪽)과 1px 오프셋 (상하와 오른쪽)을 추가합니다
  • Chrome은 1px 삽입 (상단 및 왼쪽)과 1px 오프셋 (하단 및 오른쪽)을 추가합니다

지금까지 내 유일한 해결책은 실제 테두리를 직접 (아마도 path도구를 사용하여 ) 그려서 테두리를 획 요소 뒤에 배치하는 것입니다. 그러나이 솔루션은 불쾌한 해결 방법이며 가능한 경우이 길을 따르지 않는 것이 좋습니다.

내 질문은 SVG stroke-width에 요소를 그리는 방법을 제어 할 수 있습니까?


이를 달성하기 위해 사용할 수있는 필터 해킹이 있지만 훌륭한 솔루션은 아닙니다.
Michael Mullany

2
paint-order칠 위에 스트로크를 렌더링하도록 지정할 수 있는 매개 변수가 있습니다. 따라서 "외부 정렬"을 얻을 수 있습니다. jsfiddle.net/hne0kyLg/1
Ivan Kuckir

css 'outline-'속성을 사용하여이를 수행하는 방법을 찾았습니다 : codepen.io/badcat/pen/YVzmYY . 브라우저에서이 기능이 무엇을 지원하는지 잘 모르지만 유용 할 수 있습니다.
bplmp

답변:


375

아니요, 획을 요소 내부 또는 외부에 그릴 지 여부를 지정할 수 없습니다. 내가 만든 제안 2003 년에이 기능에 대한 SVG의 작업 그룹을하지만, 어떤 지원 (또는 토론)을 수신하지.

SVG가 제안한 스트로크 위치 예 (phrogz.net/SVG/stroke-location.svg)

제안서에서 언급했듯이

  • 스트로크 너비를 두 배로 늘리고 클리핑 패스를 사용하여 객체를 자체적으로 자르면 "내부"와 동일한 시각적 결과를 얻을 수 있습니다.
  • 획 너비를 두 배로 늘리고 획없는 객체 사본 위에 오버레이하여 '외부'와 동일한 시각적 결과를 얻을 수 있습니다.

편집 :이 답변은 나중에 틀릴 수 있습니다. 사용하여 이러한 결과를 달성 할 수 있어야한다 SVG 벡터 효과를 조합함으로써, veStrokePathveIntersect( '내부') 또는과 veExclude(외부 '의 경우). 그러나 Vector Effects는 아직 구현되지 않은 초안 모듈입니다.

편집 2 : SVG 2 드래프트 사양에 stroke-alignment속성이있다 (중앙값 이상으로). 이 속성은 결국 UA로 만들 수 있습니다.

편집 3 : 재미 있고 엉망인 SVG 작업 그룹이 stroke-alignmentSVG 2에서 제거되었습니다 . 여기서 산문 후에 설명 된 문제 중 일부를 볼 수 있습니다 .


2
그럴 수도 있다고 생각했습니다. 이 문제를 해결하기 위해 getStrokedBBox ()라는 getBBox ()에 대한 래퍼 함수를 ​​작성했습니다. 이 래퍼는 브라우저가 도형의 삽입 및 오프셋에 획을 적용하는 방법에 따라 BBox를 반환합니다. 완벽하지는 않지만 (최신 브라우저 버전을 계속 확인해야하지만) 외부 모양을 정확하게 제공합니다.
Steve

6
@Phrogz 아마도 10 년이 지나기 전에 볼 수있을 것입니다. svgwg.org/svg2-draft/painting.html#SpecifyingStrokePaint 주석
frenchone

1
드디어 왔어요! 나는이 부동산이 도착할 것을 촉구했다.
mnsth

내가 만든 SVG-윤곽 스크립트를 당신이 설명을 찾을 수 있습니다 관심있는 사람들을위한, 뇌졸중 정렬의 해결 방법으로 이용 될 수있는 SVGGeometryElement의 윤곽을 추적하는 여기
maioman

2
제안서에 투표 할 수있는 페이지가 있습니까? 감사. 말도 안되는 것 같습니다.
mahish

57

UPDATE :stroke-alignment 속성은 4 월 1 일, SVG 스트로크라는 완전히 새로운 스펙으로 이동 2015 년이었다 .

2015 년 2 월 26 일 ( 2 월 13 일 이후 ) SVG 2.0 에디터 초안 에서stroke-alignment속성이 존재 값으로 inner , center (기본)outer.

그것은 같은 방식으로 작동하는 것 같습니다 stroke-location @Phrogz하고 나중에 의해 제안 된 재산 stroke-position제안을 . 이 숙박 시설은 최소 2011 년부터 계획되었지만

SVG 2는 스트로크 위치를 지정하는 방법을 포함해야합니다

, 그것은 지금까지 연기되었던 스펙에 상세하게 설명 된 적이 없다 .

브라우저가이 속성을 지원하지 않거나 새로운 SVG 2 기능을 아직 지원하지 않지만 사양이 성숙 해지 자마자 기능이 향상 될 것입니다. 이것은 내가 개인적으로 갖고 싶었던 재산이었고, 그것이 그것이 사양에 마침내 들어서서 정말 기쁩니다.

루프뿐만 아니라 열린 경로에서 속성이 어떻게 동작해야하는지에 대한 몇 가지 문제가있는 것 같습니다. 이러한 문제는 대부분 브라우저에서 구현을 연장 할 것입니다. 그러나 브라우저 가이 속성을 지원하기 시작하면이 정보를 새로운 정보로 업데이트 할 것입니다.


1
stroke-alignmentW3C 작업 초안 인 SVG Strokes에 지정되어 있습니다. 한편 SVG 2 W3C Editor 's Draft에 따르면 스트로크 위치 지정 속성은 svgwg.org/svg2-draft/painting.html#SpecifyingStrokePaint 의 SVG 사양에 있어야 하지만 해당 사양은 이미 W3C 후보 권장 사항 상태에 도달했으며 그러한 속성은 없습니다. stroke-position제안서에 대한 링크를 제외하고는 사양에서 그렇지 않습니다.
Patrick Dark

47

몇 가지 제한 사항이 있지만 쉬운 방법을 찾았습니다.

  • 형태를 defs로 정의
  • 모양을 참조하는 클립 경로 정의
  • 그것을 사용하고 외부가 잘릴 때 스트로크를 두 배로하십시오

다음은 실제 예입니다.

<svg width="240" height="240" viewBox="0 0 1024 1024">
<defs>
	<path id="ld" d="M256,0 L0,512 L384,512 L128,1024 L1024,384 L640,384 L896,0 L256,0 Z"/>
	<clipPath id="clip">
		<use xlink:href="#ld"/>
	</clipPath>
</defs>
<g>
	<use xlink:href="#ld" stroke="#0081C6" stroke-width="160" fill="#00D2B8" clip-path="url(#clip)"/>
</g>
</svg>


2
내가 찾은 최고의 답변
Ed Kolosovsky

1
영리한 솔루션. 감사합니다
Vince Yuan

이것은 답변으로 받아 들여 져야합니다. <defs>와 <use>를 사용하는 것이 현재 가장 유용한 솔루션입니다.
Nyerguds

좋은 해결책. 어떻게 외부 뇌졸중을 만들기 위해 그것을 뒤집을 것입니까?
Lucent

왜 최상위 <use>인가? 패스와 클립 패스를 직접 넣지 않는 이유는 무엇입니까? 이것은 잘 작동합니다 : <svg width="240" height="240" viewBox="0 0 1024 1024"> <path id="ld" d="M256,0 L0,512 L384,512 L128,1024 L1024,384 L640,384 L896,0 L256,0 Z" clip-path="url(#clip)" stroke="#0081C6" stroke-width="160" fill="#00d2b8"/> <clipPath id="clip"> <use xlink:href="#ld"/> </clipPath> </svg>. (예, 이것은 완전히 합리적이고 올바른 SVG이며 모든 곳에서 올바르게 렌더링됩니다. 재귀를 두려워하지 마십시오.)
Chris Morgan

30

CSS를 사용하여 획 및 채우기 순서를 지정할 수 있습니다. 즉, 먼저 스트로크 한 다음 두 번째로 채우고 원하는 효과를 얻습니다.

MDN paint-order: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/paint-order

CSS 코드 :

paint-order: stroke;

이것은 완벽 해요! 공유해 주셔서 감사합니다
BrunoFenzl

1
연결된 문서에 스트로크가 내부, 외부 또는 중앙에 있는지 여부가 표시되어 있지 않습니까? 스트로크가 그려지는 위치를 제어하는 ​​방법을 설명해 주시겠습니까? 감사.
Crashalot

2
스트로크는 항상 그랬던 것처럼 중앙에 배치됩니다. 그러나 솔리드 채우기가있는 경우 먼저 페인트 순서를 페인트 스트로크로 조정하는 효과는 스트로크의 안쪽 절반이 페인트되는 것입니다. 바깥 쪽의 두께는 절반 정도입니다.
Chris Morgan

7

주어진 스트로크를 사용하여 브라우저를 기준으로 상단, 오른쪽, 하단 및 왼쪽에 추가해야 할 픽셀 수를 계산하는 함수는 다음과 같습니다.

var getStrokeOffsets = function(stroke){

        var strokeFloor =       Math.floor(stroke / 2),                                                                 // max offset
            strokeCeil =        Math.ceil(stroke / 2);                                                                  // min offset

        if($.browser.mozilla){                                                                                          // Mozilla offsets

            return {
                bottom:     strokeFloor,
                left:       strokeFloor,
                top:        strokeCeil,
                right:      strokeCeil
            };

        }else if($.browser.webkit){                                                                                     // WebKit offsets

            return {
                bottom:     strokeCeil,
                left:       strokeFloor,
                top:        strokeFloor,
                right:      strokeCeil
            };

        }else{                                                                                                          // default offsets

            return {
                bottom:     strokeCeil,
                left:       strokeCeil,
                top:        strokeCeil,
                right:      strokeCeil
            };

        }

    };

6

위의 사람들이 언급했듯이 SVG는 기본적으로 Illustrator의 획 정렬을 지원하지 않을뿐만 아니라 PostScript는 획의 경로 좌표에 대한 오프셋을 다시 계산하거나 너비를 두 배로 늘린 다음 한쪽을 마스크해야합니다. .

어도비의 포스트 스크립트 매뉴얼 2 판 상태에서 스트로크 사양은 " 4.5.1 쓰 다듬어 : 스트로크 운영자는 현재의 경로를 따라 몇 가지 두께의 선을 그립니다 경로의 각 직선 또는 곡선 세그먼트를 들어,. 스트로크가 되어 줄립니다 중심 에를 측면이 평행 한 세그먼트 을 가진 세그먼트" (강조)

사양의 나머지 부분에는 선의 위치를 ​​상쇄하기위한 속성이 없습니다. Illustrator에서 내부 또는 외부를 정렬 할 수있는 경우 실제 경로의 오프셋을 다시 계산합니다 (여전히 인쇄 한 후 마스킹하는 것보다 계산 비용이 저렴하기 때문입니다). .ai 문서의 경로 좌표는 참조 형식이며 래스터 화되거나 최종 형식으로 내보내지는 것은 아닙니다.

Inkscape의 기본 형식은 사양 SVG이므로 사양에없는 기능을 제공 할 수 없습니다.


4

다음은 and를 사용하여 내부 경계 에 대한 해결 방법입니다 .rectsymboluse

: https://jsbin.com/yopemiwame/edit?html,output

SVG :

<svg>
  <symbol id="inner-border-rect">
    <rect class="inner-border" width="100%" height="100%" style="fill:rgb(0,255,255);stroke-width:10;stroke:rgb(0,0,0)">
  </symbol>
  ...
  <use xlink:href="#inner-border-rect" x="?" y="?" width="?" height="?">
</svg>

참고 : 교체해야합니다 ?use실제 값.

배경 : 기호로 대체하여 새 뷰포트 설정 때문에이 작품 이유는 symbolsvg와 그림자 DOM의 요소를 생성합니다. 그러면 svg그림자 DOM이 현재 SVG요소에 연결됩니다 . 주의 svg의는 중첩 될 수 있습니다 모든이 svg새로운 뷰포트를 생성하는 클립 중복이 중첩 경계부를 포함하여 모든 것이. 무슨 일이 일어나고 있는지에 대한 더 자세한 개요는 Sara Soueidan 의이 환상적인 기사 를 읽으 십시오.


2

얼마나 도움이 될지 모르겠지만 제 경우에는 테두리 만있는 다른 원을 만들어 다른 모양의 "내부"에 배치했습니다.


0

(더러운) 가능한 해결책은 패턴을 사용하는 것입니다.

내부에 획이있는 삼각형이있는 예는 다음과 같습니다.

https://jsfiddle.net/qr3p7php/5/

<style>
#triangle1{
  fill: #0F0;
  fill-opacity: 0.3;
  stroke: #000;
  stroke-opacity: 0.5;
  stroke-width: 20;
}
#triangle2{
  stroke: #f00;
  stroke-opacity: 1;
  stroke-width: 1;
}    
</style>

<svg height="210" width="400" >
    <pattern id="fagl" patternUnits="objectBoundingBox" width="2" height="1" x="-50%">
        <path id="triangle1" d="M150 0 L75 200 L225 200 Z">
    </pattern>    
    <path id="triangle2" d="M150 0 L75 200 L225 200 Z" fill="url(#fagl)"/>
</svg>

0

Xavier Ho 의 솔루션채우기가 투명하지 않은 단색 일 경우에만 작동하지만 스트로크 너비를 두 배로 늘리고 페인트 순서를 변경하는 의 은 훌륭합니다.

더 복잡한 다른 접근법을 개발했지만 모든 채우기에 효과적입니다. 타원이나 경로에서도 작동합니다 (나중에 이상한 행동을하는 코너 케이스가 있습니다 (예 : 자신을 가로 지르는 열린 경로이지만 많이는 아닙니다)).

트릭은 모양을 두 개의 레이어로 표시하는 것입니다. 하나는 획이없는 (채우기 만), 다른 하나는 굵기가 두 배인 획이있는 (투명한 채우기) 전체 모양을 표시하지만 획이없는 원래 모양을 숨기는 마스크를 통과했습니다.

  <svg width="240" height="240" viewBox="0 0 1024 1024">
  <defs>
    <path id="ld" d="M256,0 L0,512 L384,512 L128,1024 L1024,384 L640,384 L896,0 L256,0 Z"/>
    <mask id="mask">
      <use xlink:href="#ld" stroke="#FFFFFF" stroke-width="160" fill="#FFFFFF"/>
      <use xlink:href="#ld" fill="#000000"/>
    </mask>
  </defs>
  <g>
    <use xlink:href="#ld" fill="#00D2B8"/>
    <use xlink:href="#ld" stroke="#0081C6" stroke-width="160" fill="red" mask="url(#mask)"/>
  </g>
  </svg>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.