使用 React 在 SVG 中居中文本
Center text in SVG with React
首先,是的,我进行了搜索并且看到了许多其他可用的答案。但他们对我不起作用。
我希望能够使我的 SVG 中的文本居中。
因为我必须能够将它放在左侧、中间或右侧(水平和垂直方向),所以我尝试变得有点通用并以编程方式计算 x 和 y。
这是一个例子:https://codesandbox.io/s/ll6ppwkyq7
您可以在结果中看到文本没有垂直居中。
红色方框是文字的边框。
黑框是我应该居中的框。
元素的x坐标与文本右位置坐标的关系与元素的 y 坐标和 bottom 位置。其实是颠倒的。
这是因为在垂直方向上,文本位于元素的底部,y 坐标从上到下,而水平坐标与文本的方向相同。
这在使用您正在使用的 GetBBbox() 方法时很容易看到。例如,当在 x 和 y 的坐标 0 处添加文本元素时,您会看到 getBBbox 会给您一个 x = 0 但一个负的 y。
console.log(document.getElementById('testbbox').getBBox());
<svg id="testbbox"><text x=0 y=0>test</text></svg>
因此,使文本居中的计算方式已经有所不同。你现在拥有的是:
outerRect.x - ((outerRect.width - innerRect.width) / 2)
之所以可行,是因为您假设内部矩形从 0 开始,但事实并非如此。您的边界框垂直为负。所以完整的公式应该是这样的:
outerRect.x - innerRect.x - ((outerRect.width - innerRect.width) / 2)
在你的例子中是:
x - bboxx + ( (width - boxWidth) / 2)
其中 bbox 是 x 的 getBBox()
你可以使用基线,但是 dy 在 tspan 上,这使得计算有点复杂,不确定是不是好方法。由于无论如何 getBBox 在计算中都考虑了基线,所以它并不是真正必要的。
另外,如果你看这里,文本的基线应该是显性基线,而不是对齐基线:https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/dominant-baseline
看看它是如何影响边界框的,尤其是y坐标:
console.log(document.getElementById('central').getBBox());
console.log(document.getElementById('top').getBBox());
<svg id="central">
<text y=10 dominant-baseline="central" >test</text>
</svg>
<svg id="top">
<text y=10 dominant-baseline="top" >test</text>
</svg>
首先,是的,我进行了搜索并且看到了许多其他可用的答案。但他们对我不起作用。
我希望能够使我的 SVG 中的文本居中。
因为我必须能够将它放在左侧、中间或右侧(水平和垂直方向),所以我尝试变得有点通用并以编程方式计算 x 和 y。
这是一个例子:https://codesandbox.io/s/ll6ppwkyq7
您可以在结果中看到文本没有垂直居中。
红色方框是文字的边框。
黑框是我应该居中的框。
元素的x坐标与文本右位置坐标的关系与元素的 y 坐标和 bottom 位置。其实是颠倒的。
这是因为在垂直方向上,文本位于元素的底部,y 坐标从上到下,而水平坐标与文本的方向相同。
这在使用您正在使用的 GetBBbox() 方法时很容易看到。例如,当在 x 和 y 的坐标 0 处添加文本元素时,您会看到 getBBbox 会给您一个 x = 0 但一个负的 y。
console.log(document.getElementById('testbbox').getBBox());
<svg id="testbbox"><text x=0 y=0>test</text></svg>
因此,使文本居中的计算方式已经有所不同。你现在拥有的是:
outerRect.x - ((outerRect.width - innerRect.width) / 2)
之所以可行,是因为您假设内部矩形从 0 开始,但事实并非如此。您的边界框垂直为负。所以完整的公式应该是这样的:
outerRect.x - innerRect.x - ((outerRect.width - innerRect.width) / 2)
在你的例子中是:
x - bboxx + ( (width - boxWidth) / 2)
其中 bbox 是 x 的 getBBox()
你可以使用基线,但是 dy 在 tspan 上,这使得计算有点复杂,不确定是不是好方法。由于无论如何 getBBox 在计算中都考虑了基线,所以它并不是真正必要的。
另外,如果你看这里,文本的基线应该是显性基线,而不是对齐基线:https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/dominant-baseline
看看它是如何影响边界框的,尤其是y坐标:
console.log(document.getElementById('central').getBBox());
console.log(document.getElementById('top').getBBox());
<svg id="central">
<text y=10 dominant-baseline="central" >test</text>
</svg>
<svg id="top">
<text y=10 dominant-baseline="top" >test</text>
</svg>