text垂直居中 - 如何在SVG矩形中放置和居中文本




svg text垂直居中 (5)

我有以下矩形...

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

我想将“小说”一词置于其中。 对于其他矩形,svg文字是否会保留在其中? 我似乎无法找到任何关于将文本插入以水平和垂直为中心的形状以及文字包装的具体内容。 此外,文本不能离开矩形。

查看http://www.w3.org/TR/SVG/text.html#TextElement示例并没有帮助,因为文本元素的x和y不同于矩形的x和y。 文字元素似乎没有宽度和高度。 我不确定这里的数学。

(我的HTML表格不起作用。)


SVG 1.2 Tiny添加了文本包装,但是在浏览器中找到的大多数SVG实现(除Opera之外)都未实现此功能。 开发人员通常需要手动定位文本。

SVG 1.1规范很好地概述了这种限制,并提供了克服它的可能解决方案:

每个“文本”元素都会导致呈现单个字符串文本。 SVG不执行自动换行或换行。 要实现多行文本的效果,请使用以下方法之一:

  • 作者或创作包需要预先计算换行符并使用多个“文本”元素(每行文本一个)。
  • 作者或创作包需要预先计算换行符,并为属性“x”,“y”,“dx”和“dy”使用带有一个或多个“tspan”子元素的单个“文本”元素,为那些开始新行的字符设置新的起始位置。 (这种方法允许跨多行文本选择用户文本 - 请参阅文本选择和剪贴板操作。)
  • 将文本显示在另一个XML名称空间中,例如内联嵌入“foreignObject”元素中的XHTML [XHTML]。 (注意:此方法的确切语义在此时尚未完全定义。)

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 : http://wiki.inkscape.org/wiki/index.php/FAQ#What_about_flowed_text.3F

此外,还有一些JavaScript库可用于动态自动化文本换行: http://www.carto.net/papers/svg/textFlow/ : http://www.carto.net/papers/svg/textFlow/

有趣的是,CSVG的解决方案是将形状封装到文本元素中(例如,参见他们的“按钮”示例),尽管提及它们的实现在浏览器中不可用是很重要的: http://www.csse.monash.edu.au/~clm/csvg/about.html : http://www.csse.monash.edu.au/~clm/csvg/about.html

我提到这一点是因为我开发了一个CSVG启发式库,允许您执行类似的事情,并且可以在Web浏览器中工作,尽管我还没有发布它。


以前的答案在使用圆角或大于1的stroke-width时效果不佳。 例如,你会期望下面的代码产生一个圆角的矩形,但是角落被父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 ,然后将新的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)"属性翻译了矩形/文本组transform="translate(x,y)"以证明这提供了一种更直观的方法来在屏幕上定位矩形/文本。


全部细节博客​​: http://blog.techhysahil.com/svg/how-to-center-text-in-svg-shapes/ : 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>


在SVG中水平和垂直居中文本的简单解决方案:

  1. 将文本的位置设置为要将其居中的元素的绝对中心

    • 如果是父母,你可以做x="50%" y ="50%"
    • 如果它是另一个元素, x将是该元素的x +宽度的一半(对于y是高度,但类似)。
  2. 使用text-anchor属性将文本水平居中并使用值middle值:

    中间

    呈现的字符对齐,使得生成的呈现文本的几何中间位于最初的当前文本位置。

  3. 使用alignment-baseline属性可以将文本垂直middle放置在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>


我有一次使用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);
}




svg