SVGの長方形にテキストを配置して中央揃えにする方法


179

次の長方形があります...

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

その中の「フィクション」という言葉を中心にしたいと思います。他の四角形の場合、SVGワードラップは四角形内にとどまりますか?水平方向と垂直方向の両方で中央揃えになっている図形内にテキストを挿入したり、ワードラップしたりすることについて、特に何も見つからないようです。また、テキストは長方形を離れることはできません。

http://www.w3.org/TR/SVG/text.html#TextElementを見る例を、テキスト要素のxとyは長方形のxとyとは異なるため、役に立ちません。テキスト要素の幅と高さがないようです。ここでの数学はわかりません。

(私のhtmlテーブルは機能しません。)


1
テキストアンカーとドミナントベースラインを使用して回答に切り替えてもらえますか?ありがとう!
-neaumusic

1
neaumusic、完了しました。8)
レディーアリーナ

回答:


309

SVGでテキストを水平および垂直に中央揃えする簡単なソリューション:

  1. テキストの位置を、テキストを中央に配置する要素の絶対的な中央に設定します。

    • それが親である場合、あなたはただすることができますx="50%" y ="50%"
    • それは別の要素だ場合、xだろうx、その要素の+の半分の幅(およびのための同様の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
私はどこでもこれほど簡単な解決策を探していました-放射状プログレスバー内の数値を
中央に配置

7
私の場合、それはdominant-baseline仕事ではなく、プロパティですalignment-baseline
pintoch

1
これを定期的に行う場合は、以下を追加することもできます<style type="text/css"><![CDATA[ text { alignment-baseline: middle; text-anchor:middle; } ]]></style>。解決策をありがとう。
Manngo 2017

1
独自のコードスニペットを実行します。動かない。確認してください:それも、stackoverflow自体によって提供されるプレビューでは機能しません。前にコメントで述べたように、dominant-baseline実際に使用する必要があります。申し訳ありませんが、この回答は誤解を招くものです。FirefoxでもChromiumでも機能しないようであり、さらに、自分で正しい解決策を見つけるためにコメントを調査する必要があるので、期待どおりに機能するコードで別の回答を自由に追加しました。(記録用:Ubuntu Linux上のFFおよびChromiumでテスト済み。)
Regis May

2
@RegisMay指摘してくれてありがとう。私は、Mac上のChromeで午前、それがで罰金を働いたalignment-baselineが、スペックを見直し、それがあるべきので、それは風変わりなものであってもよいことと思われるdominant-baselineためtext、とalignment-baselineのためにtspantrefaltGlyph、とtextPath。私はそれに応じて答えを更新しました。
アルバロモントロ2018年

38

SVG 1.2小さなテキストの折り返しが追加されましたが、ブラウザーに表示されるSVGのほとんどの実装(Operaを除く)はこの機能を実装していません。通常、テキストを手動で配置するのは開発者の責任です。

SVG 1.1仕様は、この制限の概要と、それを克服するための可能な解決策を提供します。

各 'text'要素により、テキストの単一の文字列がレンダリングされます。SVGは自動改行やワードラップを行いません。複数行のテキストの効果を得るには、次のいずれかの方法を使用します。

  • 著者またはオーサリングパッケージは、改行を事前に計算し、複数の「テキスト」要素(テキストの各行に1つ)を使用する必要があります。
  • 著者またはオーサリングパッケージは、改行を事前に計算し、属性「x」、「y」、「dx」、および「dy」に適切な値を持つ1つ以上の「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

まだリリースしていませんが、同様のことができ、Webブラウザーで機能するCSVGにインスパイアされたライブラリーを開発したので、これについて言及します。


返信ありがとうございます...しかし、ACK!その場合、svgをダンプする必要があるようです。開発者が最初に考えなければならないことの1つは、(ユーザーの希望どおりにフォーマットされた)テキストを図形に添付することでした!彼らが一緒に行動するまで、私はもうそれをやる前に待ちます。私はそれをWindowsペイントで再描画して、それがうまくいくかどうかを確認します。(ブラウザにテーブルを正しく表示させることができた場合に限ります。)
Lady Aleena

svgの編集可能なテキストについて、OperaはSVG 1.2 Tinyの編集可能な属性をサポートしています。これによりeditable="true"、textまたはtextArea要素に属性を追加するだけで編集可能なテキストを取得できます。
ErikDahlström11年

2
@エリック、もう一度オペラは時代遅れです。
jbeard4

@Lady Aleena、私が言及したInkscapeソリューションを使ってみませんか?それが静的な画像のみの場合(たとえば、動的な動作がない、テキストコンテンツを動的に更新しない)場合、これは正常に機能します。さらに、Paintがラスターグラフィックスを生成するため、Paintは拡張できません。最後に、Paintがどのレベルでもテキストの折り返しをサポートしているとは思いません。
jbeard4

@ echo-flow htmlを生成するためにMicrosoft Front Pageを使用(そしてその後ダンプ)してからずっと前に、コード生成プログラムに対するすべての信頼を失いました。私は常に、自分が書いているものに独自のコードを追加するプログラムには警戒しています。フロントページは本当に私のhtmlを台無しにしました。Inkscapeユーザーの場合、Inkscapeが独自の独自のコードをsvgに配置しているかどうかを教えてください。svgの作成後に、そこに移動して削除する必要があります。
Lady Aleena、2011

23

角が丸い、またはstroke-width> 1 を使用すると、以前の回答では不十分な結果が得られました。たとえば、次のコードでは角丸四角形が生成されると予想されますが、コーナーは親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してsvgから、そのnew svgとをrect一緒にg要素内にネストすることをお勧めします。

<!--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-baselinetext-anchor、ではないdominantBaselinetextAnchor
Nathaniel M. Beaver

1
@ NathanielM.Beaverはい、そうなるはずです。良いキャッチ。上記のコードはReactのもので、残念ながらキャメルケースを使用して属性の名前を変更する必要があります。
ブレナン・チャン、

13

text-anchor = "middle"プロパティを直接使用できます。長方形とテキストの上にラッパーsvg要素を作成することをお勧めします。そうすれば、1つの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>


他の解決策はあるが、Firefoxを中心にしていない。 codepen.io/anon/pen/oEByYr
tgf

私はFirefox 58.0.1(64ビット)でテストしましたが、動作しています。それがあなたのためにうまくいっていないバージョンについて言及できますか?
Sahil Gupta

Firefox 58.0.2 64ビット。テキストは本来あるべきものよりわずかに高くなっています。最初は簡単に目立たないかもしれませんが、ボックスが非常にぴったりと合っている場合は、より明白です。高さを下げてみてください。
tgf 2018

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

長方形の中にテキストを挿入する1つの方法は、外部オブジェクトを挿入することです。これは、rectオブジェクトの中に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-edgehangingインド語のスクリプト用に設計されているため、これもおそらく間違ってい ます。もちろん、ラテン語、インド語、表意文字などを組み合わせて使用​​している場合は、おそらくドキュメントを読む必要があります

/* 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}

編集:私はMozilladominant-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.