2011-04-05 97 views
67

地方和中央的文字,我有以下矩形...如何在SVG矩形

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

我想中心的這裏面的單詞「小說」。對於其他矩形,svg文字是否會保留在其中?我似乎無法找到任何關於將文本插入以水平和垂直爲中心的形狀以及文字包裝的具體內容。此外,文本不能離開矩形。

看看http://www.w3.org/TR/SVG/text.html#TextElement示例沒有幫助,因爲文本元素的x和y不同於矩形的x和y。文字元素似乎沒有寬度和高度。我不確定這裏的數學。

(我的HTML表格僅僅是行不通的。)

回答

32

SVG 1.2微小添加文本換行,但SVG的大多數實現,你將在瀏覽器(使用Opera除外),找到還沒有實現這個特徵。開發人員通常需要手動定位文本。

的SVG 1.1規範提供此限制的一個很好的概述,以及可能的解決方案來克服它:

每個「文本」元件導致單個 串的文本要被渲染。 SVG 不執行自動換行或 換行。達到的效果的多行文本 ,使用 下列方法之一:

  • 作者或製作包需要 預先計算換行,並使用 多個「文本」元件(一個用於每行 一行文字)。
  • 作者或製作 包需要預先計算線 場所及使用單一的「文本」元件 與一個或多個「TSPAN」子 元件具有用於 屬性「x」的適當的值,「Y」 ,'dx'和'dy'爲 爲那些創建新行的 字符設置了新的起始位置。 (這種方法允許用戶文本跨越 多行文本 選擇 - 見文本選擇和 剪貼板操作)
  • 抒解 文本到另一個XML命名空間 來呈現諸如XHTML [XHTML] 嵌入內聯在 'foreignObject'元素內。 (注:此方法的 確切語義 沒有完全此時所定義。)

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的解決方案,包裝的形狀到一個文本元素(例如,見他們的「按鈕」的例子),儘管它一提的是其實施是在瀏覽器中沒有使用是很重要的: http://www.csse.monash.edu.au/~clm/csvg/about.html

我提到這一點,因爲我已經開發出一種CSVG風格庫,使ÿ你做類似的事情,並在網頁瀏覽器中工作,雖然我還沒有發佈它。

+4

而且甚至沒有讓我開始對什麼是參與創造* *可編輯的文本... – jbeard4 2011-04-05 04:35:34

+0

感謝您的答覆...但是ACK!看來,我將不得不轉儲svg。開發人員應該考慮的第一件事情之一是將文本(用戶希望的格式)附加到形狀上!我會等到他們一起行動起來,然後再做。我將嘗試在Windows Paint中重新繪製它,看看是否可以做到這一點。 (如果我只能讓瀏覽器正確顯示錶格)。 – 2011-04-05 06:44:16

+0

關於svg中的可編輯文本,Opera支持SVG 1.2 Tiny中的editable屬性,它可以通過簡單添加一個屬性'editable =「true來獲得可編輯文本「'給text或textArea元素。 – 2011-04-05 07:16:03

1

我有一次使用SVG獲取任何東西的bug,所以我推出了自己的小功能。希望它能幫助你。請注意,它僅適用於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); 
} 
83

一個簡單的解決方案,以水平和垂直居中文本在SVG:

  1. 設置文本的位置的元素在其中要居中它絕對中心

    • 如果是父母,那麼您可以做x="50%" y ="50%"
    • 如果是另一個元素,則x將是該元素的x +其寬度的一半(並且與y類似,但是具有高度)。
  2. 使用text-anchor屬性文本與值middle水平居中:

    中間

    渲染字符被對準,使得所得到的呈現的文本的幾何中間是在最初的當前文本位置。

  3. 使用alignment-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%" alignment-baseline="middle" text-anchor="middle">TEXT</text>  
 
</svg>

+0

我一直在尋找一個解決方案這個簡單的地方 - 沒有別的工作對我來說我用這個在放射狀的進度條裏面對一個數字進行居中 – anthonytherockjohnson 2017-04-18 11:53:05

+3

在我的情況下,它是執行工作的「顯性 - 基線」屬性,而不是'alignment-baseline'。 – pintoch 2017-05-01 22:41:50

+0

不幸的是,這個解決方案剪切矩形筆畫。請參閱下面的示例以瞭解避免剪輯的解決方案:https://stackoverflow.com/a/44857272/3795219 – 2017-07-01 04:29:01

4

您可以直接使用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> 
+0

編輯。謝謝。 – 2016-08-13 19:47:54

0

在矩形內插入文本的一種方法是在rect對象內插入一個外部對象,這是一個DIV。

通過這種方式,文本將壓縮DIV的限制。

var g = d3.select("svg"); 
 
\t \t \t \t \t 
 
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>

+0

歡迎來到Stack Overflow!請隨時參加本網站的[tour](// stackoverflow.com/tour),如果您需要網站的其他幫助,請查看[this](// stackoverflow.com/help)。哦,如果您遇到過幫助頁面未涵蓋的問題,請隨時諮詢[meta](// meta.stackoverflow.com/)。 – 2017-06-20 15:14:59

5

以前的答案使用圓角或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>

相反,我建議包裝在svgtext和然後將該新的svgrect嵌套在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)"屬性翻譯了矩形/文本組,以證明這提供了一種更直觀的方法來在屏幕上定位矩形/文本。

2

全面詳細的博客: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>

+0

其他解決方案不在Firefox中。 https://codepen.io/anon/pen/oEByYr – tgf 2018-02-09 00:17:55

+0

我在Firefox 58.0.1(64位)上測試過,它工作正常。你能否提到它不適合你的版本? – 2018-02-20 19:46:52

+0

Firefox 58.0.2 64bit。文本略高於應該。起初它可能不容易被注意到,但如果你的盒子非常緊密,它就更加明顯;嘗試減少身高。 – tgf 2018-02-21 22:32:40