web-dev-qa-db-ja.com

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

私は次の長方形を持っています...

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

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

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

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

110
Lady Aleena

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>
191
Alvaro Montoro

SVG 1.2 Tinyはテキストの折り返しを追加しましたが、ブラウザーで見つかるほとんどのSVG実装(Operaを除く)はこの機能を実装していません。通常、テキストを手動で配置するのは開発者であるあなた次第です。

SVG 1.1仕様は、この制限の優れた概要と、それを克服する可能なソリューションを提供します。

各「テキスト」要素により、単一のテキスト文字列がレンダリングされます。 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で目的のシェイプと目的のテキストを選択し、[テキスト]-> [フレームへのフロー]を使用します。これにより、ラッピングを使用してテキストを記述できます。ラッピングは、図形の境界に基づいてラップされます。また、InkscapeにSVG 1.1との互換性を維持するよう指示するには、次の指示に従ってください。 http://wiki.inkscape.org/wiki/index.php/FAQ#What_about_flowed_text.3F

さらに、テキストの折り返しを動的に自動化するために使用できるJavaScriptライブラリがいくつかあります。 http://www.carto.net/papers/svg/textFlow/

シェイプをテキスト要素にラッピングするCSVGのソリューションに注目するのは興味深いです(たとえば、「ボタン」の例を参照)。ただし、それらの実装はnotブラウザで使用可能: http://www.csse.monash.edu.au/~clm/csvg/about.html

これについて言及しているのは、CSVGにヒントを得たライブラリを開発したためです。このライブラリを使用すると、同様のことができ、Webブラウザーで動作しますが、まだリリースしていません。

37
jbeard4

前の回答では、丸い角または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>

代わりに、次の例のように、textsvgでラップしてから、その新しいsvgrectg要素内にネストすることをお勧めします:

<!--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を画面上に配置するためのより直感的なアプローチを提供することを実証しました。

19
Austin D

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>
10
Nalin Agrawal

プログラムでSVGを作成している場合は、SVGを単純化して次のようにすることができます。

  <g>
      <rect x={x} y={y} width={width} height={height} />
      <text
          x={x + width / 2}
          y={y + height / 2}
          dominantBaseline="middle"
          textAnchor="middle"
      >
          {label}
      </text>
  </g>
6
Brennan Cheung

詳細ブログ: 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>
5
Sahil Gupta

長方形内にテキストを挿入する1つの方法は、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>
2
Bruno Bastos

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
Regis May

グラフィックス内のテキストの水平および垂直方向の配置には、次の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}

編集: Mozilladominant-baseline:baselineを使用していることに気づきましたが、これは間違いです。認識された値すらありません!フォントのデフォルトであるalphabeticにデフォルト設定されていると思うので、彼らは幸運に恵まれました。

詳細編集:Safari(11.1.2)はtext-before-Edgeを理解しますが、text-after-Edgeは理解しません。 ideographicでも失敗します。素晴らしいもの、アップル。そのため、alphabeticの使用を強制され、結局は子孫を許可することになります。ごめんなさい。

1
Adam Chalcraft

私は、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
john ktejik