SVG 사각형에 텍스트를 배치하고 중앙에 배치하는 방법


179

다음 사각형이 있습니다 ...

<rect x="0px" y="0px" width="60px" height="20px"/>

나는 그 안에 "Fiction"이라는 단어를 중심으로하고 싶습니다. 다른 사각형의 경우 svg word wrap이 그 안에 머물러 있습니까? 가로 및 세로 중앙에 배치 된 도형과 텍스트 줄 바꿈에 텍스트를 삽입하는 것에 대해 구체적으로 찾을 수없는 것 같습니다. 또한 텍스트는 사각형을 떠날 수 없습니다.

텍스트 요소의 x 및 y가 사각형의 x 및 y와 다르기 때문에 http://www.w3.org/TR/SVG/text.html#TextElement 예제를 보면 도움이되지 않습니다. 텍스트 요소의 너비와 높이가없는 것 같습니다. 나는 여기서 수학을 확신하지 못한다.

(html 테이블이 작동하지 않습니다.)


1
텍스트 앵커와 지배적 기준을 사용하여 답변으로 전환 할 수 있습니까? 감사!
neaumusic

1
neaumusic, 완료 8)
레이디 Aleena

답변:


310

SVG에서 텍스트를 가로 및 세로로 가운데 맞추는 쉬운 솔루션 :

  1. 텍스트의 위치를 가운데맞추려 는 요소 의 절대 중심 으로 설정하십시오.

    • 부모라면 할 수 있습니다 x="50%" y ="50%".
    • 또 다른 요소의 경우, xx(과 유사한 그 요소 + 절반 폭 y하지만 높이).
  2. text-anchor속성을 사용하여 텍스트를 값의 가로 가운데에 맞추십시오 middle.

    가운데

    렌더링 된 문자는 결과 렌더링 된 텍스트의 기하학적 중간이 초기 현재 텍스트 위치에 있도록 정렬됩니다.

  3. dominant-baseline속성을 사용하여 텍스트를 값의 세로 중앙에 middle놓으십시오 (또는 원하는 모양에 따라 수행 할 수 있음 central)

간단한 데모는 다음과 같습니다.

<svg width="200" height="100">
  <rect x="0" y="0" width="200" height="100" stroke="red" stroke-width="3px" fill="white"/>
  <text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle">TEXT</text>    
</svg>


1
아무것도 다른 나를 위해 일하는 내가 방사형 진행 막대 내부의 수를 중심으로이 사용 - 나는 해결책이 간단한 사방을 찾고있다
anthonytherockjohnson을

7
필자의 경우, dominant-baseline작업이 아닌 속성입니다 alignment-baseline.
pintoch

1
이 작업을 정기적으로 수행하려는 경우 다음을 추가 할 수도 있습니다 <style type="text/css"><![CDATA[ text { alignment-baseline: middle; text-anchor:middle; } ]]></style>.. 솔루션 주셔서 감사합니다.
Manngo

1
자신의 코드 스 니펫을 실행하십시오. 작동하지 않습니다. 확인 : stackoverflow 자체에서 제공하는 미리보기에서는 작동하지 않습니다. 주석에서 이전에 언급했듯이 dominant-baseline실제로 사용해야합니다. 죄송 합니다만이 답변은 오해의 소지가 있습니다. Firefox 또는 Chromium에서 작동하지 않는 것 같으며 자신에게 올바른 솔루션을 찾기 위해 주석을 연구해야합니다. 예상대로 작동하는 코드로 다른 답변을 추가 할 수있는 자유를 얻었습니다. (레코드 : Ubuntu Linux에서 FF 및 Chromium으로 테스트되었습니다.)
Regis가

2
@RegisMay 지적 해 주셔서 감사합니다. 나는 Mac에서 크롬 오전과 함께 벌금을했다 alignment-baseline,하지만 사양을 검토, 그것이 있어야 있기 때문에 기발한 일이 될 수 있다는 것 dominant-baseline을 위해 text, 그리고 alignment-baseline에 대한 tspan, tref, altGlyph,와 textPath. 이에 따라 답변을 업데이트했습니다.
Alvaro Montoro

38

SVG 1.2 Tiny는 텍스트 줄 바꿈을 추가했지만 브라우저에서 찾을 수있는 대부분의 SVG 구현 (Opera 제외)은이 기능을 구현하지 않았습니다. 텍스트를 수동으로 배치하는 것은 일반적으로 개발자의 책임입니다.

SVG 1.1 사양은이 제한에 대한 개요와이를 극복 할 수있는 솔루션을 제공합니다.

각 'text'요소는 단일 텍스트 문자열을 렌더링합니다. SVG는 자동 줄 바꿈이나 자동 줄 바꿈을 수행하지 않습니다. 여러 줄의 텍스트 효과를 얻으려면 다음 방법 중 하나를 사용하십시오.

  • 제작자 또는 제작 패키지는 줄 바꿈을 미리 계산하고 여러 '텍스트'요소 (각 텍스트 줄마다 하나씩)를 사용해야합니다.
  • 제작자 또는 제작 패키지는 줄 바꿈을 미리 계산하고 속성 'x', 'y', 'dx'및 'dy'에 적절한 값을 가진 하나 이상의 'tspan'자식 요소가있는 단일 'text'요소를 사용해야합니다. 줄 바꾸기를 시작하는 캐릭터의 새로운 시작 위치를 설정합니다. 이 방법을 사용하면 여러 줄의 텍스트에서 사용자 텍스트를 선택할 수 있습니다 (텍스트 선택 및 클립 보드 작업 참조).
  • 'foreignObject'요소 내에 인라인으로 포함 된 XHTML [XHTML]과 같은 다른 XML 네임 스페이스에서 렌더링되도록 텍스트를 표현하십시오. (참고 :이 방법의 정확한 의미는 현재 완전히 정의되지 않았습니다.)

http://www.w3.org/TR/SVG11/text.html#Introduction

기본적으로 dy속성과 tspan요소 를 사용하여 텍스트 줄 바꿈을 시뮬레이션 할 수 있으며 사양에서 언급 한대로 일부 도구가이를 자동화 할 수 있습니다. 예를 들어 Inkscape에서 원하는 모양과 원하는 텍스트를 선택하고 텍스트-> 프레임으로 이동을 사용하십시오. 이렇게하면 줄 바꿈과 함께 텍스트를 쓸 수 있으며 모양의 경계를 기준으로 줄 바꿈됩니다. 또한 다음 지침에 따라 SVG 1.1과의 호환성을 유지하도록 Inkscape에 지시 하십시오 . http://wiki.inkscape.org/wiki/index.php/FAQ#What_about_flowed_text.3F

또한 텍스트 줄 바꿈을 동적으로 자동화하는 데 사용할 수있는 JavaScript 라이브러리가 있습니다. http://www.carto.net/papers/svg/textFlow/

도형을 텍스트 요소에 래핑하는 CSVG의 솔루션에 주목하는 것은 흥미 롭습니다 (예 : "버튼"예 참조) . 브라우저에서 구현을 사용할 수 없다는 점을 언급하는 것이 중요 합니다. http://www.csse.monash.edu .au / ~ clm / csvg / about.html

나는 아직 발표하지는 않았지만 비슷한 일을 할 수 있고 웹 브라우저에서 작동하는 CSVG 영감 라이브러리를 개발했기 때문에 이것을 언급하고 있습니다.


답장을 보내 주셔서 감사합니다 ...하지만 ACK! 그런 다음 svg를 덤프 해야하는 것으로 보입니다. 개발자가 생각해야 할 첫 번째 사항 중 하나는 도형에 텍스트 (사용자가 원하는 형식)를 첨부하는 것입니다! 나는 그들이 더 이상 함께하기 전에 그들이 함께 행동 할 때까지 기다릴 것입니다. Windows Paint에서 다시 그리려고하는지 확인하겠습니다. (브라우저가 테이블을 올바르게 표시 할 수만 있다면)
Lady Aleena

svg의 편집 가능한 텍스트에 대해 Opera는 SVG 1.2 Tiny의 편집 가능한 속성을 지원하므로 editable="true"텍스트 또는 textArea 요소에 속성 을 추가하기 만하면 편집 가능한 텍스트를 얻을 수 있습니다.
Erik Dahlström

2
@Erik, 다시 한번 Opera는 앞서고 있습니다.
jbeard4

@Lady Aleena, 왜 내가 언급 한 Inkscape 솔루션을 사용하지 않습니까? 정적 이미지 일 경우 (예 : 동적 동작 없음, 텍스트 내용 업데이트 없음) 제대로 작동합니다. 또한 페인트가 래스터 그래픽을 생성하므로 페인트가 확장 할 수 없습니다. 마지막으로, 페인트가 어떤 레벨에서든 텍스트 줄 바꿈을 지원한다고 생각하지 않습니다.
jbeard4

@ echo-flow Microsoft Front Page를 사용하여 HTML을 생성 한 이후로 오래 전에 코드 생성 프로그램에 대한 모든 신뢰를 잃었습니다. 나는 항상 내가 쓰고있는 것에 독자적인 코드를 추가하는 프로그램에주의한다. 프론트 페이지가 내 HTML을 엉망으로 만들었습니다. 잉크 스케이프 사용자 인 경우, 잉크 스케이프가 svg에 고유 코드를 배치하여 svg 생성 후 들어가서 제거해야하는지 말해 줄 수 있습니까?
레이디 Aleena

23

앞의 답변은 둥근 모서리를 사용할 때 또는 stroke-width1보다 큰 결과를 얻지 못했습니다 . 예를 들어 다음 코드는 둥근 사각형을 생성하지만 모서리는 부모 svg구성 요소에 의해 잘립니다 .

<svg width="200" height="100">
  <!--this rect should have rounded corners-->
  <rect x="0" y="0" rx="5" ry="5" width="200" height="100" stroke="red" stroke-width="10px" fill="white"/>
  <text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle">CLIPPED BORDER</text>    
</svg>

대신 다음 예제 와 같이 text에 a를 래핑 svg한 다음 요소 안에 새 요소 svg와 중첩 요소 를 중첩하는 것이 좋습니다 .rectg

<!--the outer svg here-->
<svg width="400px" height="300px">

  <!--the rect/text group-->
  <g transform="translate(50,50)">
    <rect rx="5" ry="5" width="200" height="100" stroke="green" fill="none" stroke-width="10"/>
    <svg width="200px" height="100px">
      <text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle">CORRECT BORDER</text>      
    </svg>
  </g>

  <!--rest of the image's code-->
</svg>

위의 답변에서 발생하는 클리핑 문제를 해결합니다. 또한 transform="translate(x,y)"속성을 사용하여 rect / text 그룹을 번역하여 rect / text를 화면에 배치하는 데보다 직관적 인 접근 방식을 제공함을 보여줍니다.


16

프로그래밍 방식으로 SVG를 작성하는 경우 SVG를 단순화하고 다음과 같이 수행 할 수 있습니다.

  <g>
      <rect x={x} y={y} width={width} height={height} />
      <text
          x={x + width / 2}
          y={y + height / 2}
          dominant-baseline="middle"
          text-anchor="middle"
      >
          {label}
      </text>
  </g>

3
그것은 수 Shouldsn't dominant-baseline하고 text-anchor,하지 dominantBaselinetextAnchor?
Nathaniel M. Beaver

1
@ NathanielM.Beaver 그렇습니다. 잘 잡았습니다. 위의 코드는 불행히도 camelCase를 사용하여 속성의 이름을 변경 해야하는 React의 코드입니다.
Brennan Cheung

13

당신은 직접 text-anchor = "middle"속성을 사용할 수 있습니다 . 사각형과 텍스트 위에 래퍼 svg 요소를 만드는 것이 좋습니다. 그렇게하면 하나의 CSS 선택기를 사용하여 전체 요소를 사용할 수 있습니다. 텍스트의 'x'및 'y'속성을 50 %로 배치하십시오.

    <svg class="svg-rect" width="50" height="40">
        <rect x="0" y="0" rx="3" ry="3" width="50" height="40" fill="#e7e7e7"></rect>
        <text x="50%" y="50%" text-anchor="middle" stroke="black" stroke-width="1px" dy=".3em">N/A</text>
    </svg>


7

상세 블로그 : http://blog.techhysahil.com/svg/how-to-center-text-in-svg-shapes/

<svg width="600" height="600">
  <!--   Circle -->
  <g transform="translate(50,40)">
    <circle cx="0" cy="0" r="35" stroke="#aaa" stroke-width="2" fill="#fff"></circle>
    <text x="0" y="0" alignment-baseline="middle" font-size="12" stroke-width="0" stroke="#000" text-anchor="middle">HueLink</text>
  </g>
  
  <!--   In Rectangle text position needs to be given half of width and height of rectangle respectively -->
  <!--   Rectangle -->
  <g transform="translate(150,20)">
    <rect width="150" height="40" stroke="#aaa" stroke-width="2" fill="#fff"></rect>
    <text x="75" y="20" alignment-baseline="middle" font-size="12" stroke-width="0" stroke="#000" text-anchor="middle">HueLink</text>
  </g>
  
  <!--   Rectangle -->
  <g transform="translate(120,140)">
    <ellipse cx="0" cy="0" rx="100" ry="50" stroke="#aaa" stroke-width="2" fill="#fff"></ellipse>
    <text x="0" y="0" alignment-baseline="middle" font-size="12" stroke-width="0" stroke="#000" text-anchor="middle">HueLink</text>
  </g>
  
  
</svg>


다른 솔루션은 파이어 폭스의 중심에 있지 않습니다. codepen.io/anon/pen/oEByYr
tgf

Firefox 58.0.1 (64-bit)에서 테스트했는데 작동합니다. 작동하지 않는 버전을 언급 할 수 있습니까?
Sahil Gupta

Firefox 58.0.2 64 비트. 텍스트가 원래보다 약간 높습니다. 처음에는 쉽게 눈에 띄지 않을 수 있지만 상자가 매우 잘 맞으면 더 분명합니다. 높이를 줄이십시오.
tgf

6

alignment-baseline여기서 사용할 올바른 속성이 아닙니다. 정답은의 조합을 사용하는 것입니다 dominant-baseline="central"text-anchor="middle":

<svg width="200" height="100">
    <g>
        <rect x="0" y="0" width="200" height="100" style="stroke:red; stroke-width:3px; fill:white;"/>
        <text x="50%" y="50%" style="dominant-baseline:central; text-anchor:middle; font-size:40px;">TEXT</text>
    </g>
</svg>


2

사각형 안에 텍스트를 삽입하는 한 가지 방법은 이물질을 삽입하는 것입니다. 바로 사각형 개체 안에 DIV입니다.

이런 식으로 텍스트는 DIV의 한계를 나타냅니다.

var g = d3.select("svg");
					
g.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width","100%")
.attr("height","100%")
.attr("fill","#000");


var fo = g.append("foreignObject")
 .attr("width","100%");

fo.append("xhtml:div")
  .attr("style","width:80%;color:#FFF;margin-right: auto;margin-left: auto;margin-top:40px")
  .text("Mussum Ipsum, cacilds vidis litro abertis Mussum Ipsum, cacilds vidis litro abertis Mussum Ipsum, cacilds vidis litro abertis");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.js"></script>
<svg width="200" height="200"></svg>


1

SVG를 사용하여 중심에있는 것을 얻는 데 시간이 오래 걸리므로 작은 기능을 굴 렸습니다. 잘하면 그것은 당신을 도울 것입니다. SVG 요소에서만 작동합니다.

function centerinparent(element) { //only works for SVG elements
    var bbox = element.getBBox();
    var parentwidth = element.parentNode.width.baseVal.value;
    var parentheight = element.parentNode.height.baseVal.value;
    var newwidth = ((parentwidth / 2) - (bbox.width / 2)) - 2; //i start everything off by 2 to account for line thickness
    var newheight = ((parentheight / 2) - (bbox.height / 2)) - 2;
    //need to adjust for line thickness??

    if (element.classList.contains("textclass")) { //text is origined from bottom left, whereas everything else origin is top left
        newheight += bbox.height; //move it down by its height
    }

    element.setAttributeNS(null, "transform", "translate(" + newwidth + "," + newheight + ")");
    // console.log("centering BOXES:  between width:"+element.parentNode.width.baseVal.value + "   height:"+parentheight);
    // console.log(bbox);
}

1

그래픽에서 텍스트의 가로 및 세로 정렬을 위해 다음 CSS 스타일을 사용할 수 있습니다. 특히 dominant-baseline:middle상단과 하단 사이의 절반이 아니라 상단과 기준선 사이의 중간에 있기 때문에 아마도 잘못된 것입니다. 또한 일부 소스 (예 : Mozilla )가 dominant-baseline:hanging대신을 사용 합니다 dominant-baseline:text-before-edge. hanging인도 스크립트 용으로 설계 되었기 때문에 이것은 아마도 잘못된 것입니다 . 물론 라틴어, 인도어, 표의 문자 등을 혼합하여 사용하는 경우 문서 를 읽어야 합니다 .

/* Horizontal alignment */
text.goesleft{text-anchor:end}
text.equalleftright{text-anchor:middle}
text.goesright{text-anchor:start}
/* Vertical alignment */
text.goesup{dominant-baseline:text-after-edge}
text.equalupdown{dominant-baseline:central}
text.goesdown{dominant-baseline:text-before-edge}
text.ruledpaper{dominant-baseline:alphabetic}

편집 : 방금 모질라dominant-baseline:baseline 가 잘못 사용 하는 것을 보았습니다 . 인식 된 값조차 아닙니다! 글꼴 기본값 인으로 기본 설정되어 있다고 가정 alphabetic하므로 운이 좋았습니다.

추가 편집 : Safari (11.1.2)는 이해 text-before-edge하지만 이해 하지 못합니다 text-after-edge. 또한에 실패합니다 ideographic. 좋은 물건, 애플 따라서 결국 alphabetic하강 자를 사용 하고 허용 해야 할 수도 있습니다 . 죄송합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.