受控多旋转 SVG 文本元素

Controlled Multi - Rotation of SVG text elements

我真的很难理解 <text> 元素在 <svg> 中应该如何以可控的方式旋转。具体例子在这里:

<svg version="1.1" baseProfile="full" viewBox="0 0 1000 200" xmlns="http://www.w3.org/2000/svg" id="timeline-container">
  <line x1="11" x2="200" y1="11" y2="142.2" stroke="black"/>
  <line x1="200" x2="400" y1="142.2" y2="121" stroke="black"/>
  <line x1="400" x2="600" y1="121" y2="167.6" stroke="black"/>
  <line x1="600" x2="989" y1="167.6" y2="11" stroke="black"/>
  <rect stroke="black" stroke-width="2" fill="white" width="20" height="20" x="11" y="11" transform="translate(-10,-10)"/>
  <text text-anchor="end" x="17" y="32" transform="rotate(-90,17,32)" class="label-below-project-point" >abcdef</text>
  <rect stroke="black" stroke-width="2" fill="white" width="20" height="20" x="200" y="142.2" transform="translate(-10,-10)"/>
  <text x="206" y="121.2" transform="rotate(-90,206,121.2)" class="label-above-project-point" >abc</text>
  <rect stroke="black" stroke-width="2" fill="white" width="20" height="20" x="400" y="121" transform="translate(-10,-10)"/>
  <text x="406" y="100" transform="rotate(-90,406,100)" class="label-above-project-point" >abcdefghijklmnopq</text>
  <rect stroke="black" stroke-width="2" fill="white" width="20" height="20" x="600" y="167.6" transform="translate(-10,-10)"/>
  <text x="606" y="146.6" transform="rotate(-90,606,146.6)" class="label-above-project-point" >abcdefg</text>
  <rect stroke="black" stroke-width="2" fill="white" width="20" height="20" x="989" y="11" transform="translate(-10,-10)"/>
  <text text-anchor="end" x="995" y="32" transform="rotate(-90,995,32)" class="label-below-project-point" >abcdefghijklmnopqrstuvwxy</text>
</svg>

我想将文本元素旋转 90 度以水平显示它们,并在用户单击矩形时间轴点之一时将标签与它所指的时间轴矩形对齐。 更准确地说:

<text> 元素是使用提供的文本标签以编程方式生成的,因此它们可能包含 1 - 30 个字符的任意数字;导致可变宽度和高度。

示例

旋转从来没有像我期望的那样。例如,当我尝试通过将旋转原点设置为左下角并将旋转角度设置为 90 来旋转最左侧的 <text> 元素时,<text> 元素会旋转到顶部的顶部svg 的边框。不知道为什么。要重现它:

示例 2

我误会了什么?让我也用@Danny '365CSI' Engelman 提供的片段来说明我的问题:

<style>
  svg   { height: 180px }
  circle{ r:2px; fill:red }
</style>

<svg id=SVG viewbox="0 0 100 100">
  <rect width="100%" height="100%" fill="pink"></rect>

  <circle cx="25" cy="50"></circle>
  <text    x="25"  y="50" text-anchor="start" 
           transform="rotate(-90 25 50)">Hello</text>

  <circle cx="50" cy="50"></circle>
  <text    x="50"  y="50" text-anchor="end" dominant-baseline="hanging" 
           transform="rotate(90 50 50)">SVG</text>

  <circle cx="75" cy="50"></circle>
  <text    x="75"  y="50" text-anchor="middle" dominant-baseline="middle" 
           transform="rotate(-45 75 50)">World</text>
</svg>

假设我现在想将“Hello”文本元素旋转 90 度,使其水平显示,其旋转原点位于文本元素的中心。因此,我首先按如下方式计算文本元素的中心:

  1. 使用 document.getElementsByTagName("text")[0].getBBox(); 获取相关元素的维度。这个 returns 一个 SVG 矩形,高度为 16.38888931274414 个 SVG 单位,宽度为 36.10185241699219 个 SVG 单位。

  2. 我现在计算文本元素中心的坐标,如下所示:

x = 25 - 16.38888931274414 / 2 = 大约。 16.81

y = 50 - 36.10185241699219 / 2 = 大约。 31.95

  1. 我现在在transform属性中添加rotate(90 16.81 31.95),然后完全没有像预期的那样得到文本元素的90°旋转;如您所见:

<style>
  svg   { height: 180px }
  circle{ r:2px; fill:red }
</style>

<svg id=SVG viewbox="0 0 100 100">
  <rect width="100%" height="100%" fill="pink"></rect>

  <circle cx="25" cy="50"></circle>
  <text    x="25"  y="50" text-anchor="start" 
           transform="rotate(-90 25 50) rotate(90 16.81 31.95)">Hello</text>

  <circle cx="50" cy="50"></circle>
  <text    x="50"  y="50" text-anchor="end" dominant-baseline="hanging" 
           transform="rotate(90 50 50)">SVG</text>

  <circle cx="75" cy="50"></circle>
  <text    x="75"  y="50" text-anchor="middle" dominant-baseline="middle" 
           transform="rotate(-45 75 50)">World</text>
</svg>

我在这里不明白什么/我如何计算旋转中心 + 从而正确预测旋转????????

旋转还取决于 text-anchor 和其他文本定位属性。

但请注意;变换 变换 BBox,
所以 :hover 在文本

的地方工作

另见:SVG textpath, determine when text goes beyond the path

游乐场:

<style>
  svg   { height: 180px }
  circle{ r:2px; fill:red }
  text:hover{ transform:rotate(0)}
</style>

<svg id=SVG viewbox="0 0 100 100">
  <rect width="100%" height="100%" fill="pink"></rect>

  <circle cx="25" cy="50"></circle>
  <text    x="25"  y="50" text-anchor="start" 
           transform="rotate(-90 25 50)">Hello</text>

  <circle cx="50" cy="50"></circle>
  <text    x="50"  y="50" text-anchor="end" dominant-baseline="hanging" 
           transform="rotate(90 50 50)">SVG</text>

  <circle cx="75" cy="50"></circle>
  <text    x="75"  y="50" text-anchor="middle" dominant-baseline="middle" 
           transform="rotate(-45 75 50)">World</text>
</svg>

好的,知道了!主要感谢this。实际上,当您对 SVG 元素进行两次后续 rotate() 变换时,您始终需要在应用任何变换之前参考原始坐标,即使对于后续旋转也是如此。因此,按预期旋转“Hello”元素的分步方法(参见我的问题,示例 2):

州:

<style>
  svg   { height: 180px }
  circle{ r:2px; fill:red }
</style>

<svg id=SVG viewbox="0 0 100 100">
  <rect width="100%" height="100%" fill="pink"></rect>

  <circle cx="25" cy="50"></circle>
  <text    x="25"  y="50" text-anchor="start" 
           transform="rotate(-90 25 50)">Hello</text>

  <circle cx="50" cy="50"></circle>
  <text    x="50"  y="50" text-anchor="end" dominant-baseline="hanging" 
           transform="rotate(90 50 50)">SVG</text>

  <circle cx="75" cy="50"></circle>
  <text    x="75"  y="50" text-anchor="middle" dominant-baseline="middle" 
           transform="rotate(-45 75 50)">World</text>
</svg>

上面的方法是正确的,但是我应用到“Hello”元素的错误状态。要使旋转原点成为它的中心,您实际上必须回想该元素的原始状态; = 应用任何旋转之前的状态,因此:

原始状态:

<style>
  svg   { height: 180px }
  circle{ r:2px; fill:red }
</style>

<svg id=SVG viewbox="0 0 100 100">
  <rect width="100%" height="100%" fill="pink"></rect>

  <circle cx="25" cy="50"></circle>
  <text    x="25"  y="50" text-anchor="start">Hello</text>

  <circle cx="50" cy="50"></circle>
  <text    x="50"  y="50" text-anchor="end" dominant-baseline="hanging" 
           transform="rotate(90 50 50)">SVG</text>

  <circle cx="75" cy="50"></circle>
  <text    x="75"  y="50" text-anchor="middle" dominant-baseline="middle" 
           transform="rotate(-45 75 50)">World</text>
</svg>

现在,按照我的问题中描述的完全相同的方法,计算“Hello”元素中心点的坐标,使用:

document.getElementsByTagName("text")[0].getBBox()

它给你的宽度和高度:

  • 宽度:36.10185241699219
  • 身高:16.38888931274414

现在,根据“你好”元素的初始状态,计算中心坐标:

  • x = x-offset + 宽度 / 2 = 大约。 43.05
  • y = y 偏移量 - 高度 / 2 = 大约。 41.81

现在您应用所需的旋转 rotate(90 43.05 41.81),瞧:

<style>
  svg   { height: 180px }
  circle{ r:2px; fill:red }
</style>

<svg id=SVG viewbox="0 0 100 100">
  <rect width="100%" height="100%" fill="pink"></rect>

  <circle cx="25" cy="50"></circle>
  <text    x="25"  y="50" text-anchor="start" 
           transform="rotate(-90 25 50) rotate(90 43.05 41.81)">Hello</text>

  <circle cx="50" cy="50"></circle>
  <text    x="50"  y="50" text-anchor="end" dominant-baseline="hanging" 
           transform="rotate(90 50 50)">SVG</text>

  <circle cx="75" cy="50"></circle>
  <text    x="75"  y="50" text-anchor="middle" dominant-baseline="middle" 
           transform="rotate(-45 75 50)">World</text>
</svg>