2011-04-05 96 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