受控多旋转 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 度以水平显示它们,并在用户单击矩形时间轴点之一时将标签与它所指的时间轴矩形对齐。
更准确地说:
点击最左边的时间轴点时,标签旋转90度水平显示+左对齐最左边矩形的左边框
对于最右边的点,首先旋转90度以产生水平显示,然后将文本元素与最右边矩形的右边框右对齐。
对于所有的中间点,也先旋转90°水平显示,然后将文本相对于各自时间线点的中心居中对齐。
<text>
元素是使用提供的文本标签以编程方式生成的,因此它们可能包含 1 - 30 个字符的任意数字;导致可变宽度和高度。
示例
旋转从来没有像我期望的那样。例如,当我尝试通过将旋转原点设置为左下角并将旋转角度设置为 90 来旋转最左侧的 <text>
元素时,<text>
元素会旋转到顶部的顶部svg 的边框。不知道为什么。要重现它:
- 将
getBBox()
应用到文本元素上以获得其宽度 W
。
- 将
W
+text
元素的y
属性的值相加得到那个最左边的左下角的y
坐标文本元素; Y
.
- 将相应的旋转命令:
rotate(90,0,Y)
添加到最左侧文本元素的transform
元素中,您将得到:
transform="rotate(-90,17,32) rotate(90,0,Y)
。旋转完全不符合您的预期...
示例 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 度,使其水平显示,其旋转原点位于文本元素的中心。因此,我首先按如下方式计算文本元素的中心:
使用 document.getElementsByTagName("text")[0].getBBox();
获取相关元素的维度。这个 returns 一个 SVG 矩形,高度为 16.38888931274414 个 SVG 单位,宽度为 36.10185241699219 个 SVG 单位。
我现在计算文本元素中心的坐标,如下所示:
x = 25 - 16.38888931274414 / 2 = 大约。 16.81
y = 50 - 36.10185241699219 / 2 = 大约。 31.95
- 我现在在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>
我真的很难理解 <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 度以水平显示它们,并在用户单击矩形时间轴点之一时将标签与它所指的时间轴矩形对齐。 更准确地说:
点击最左边的时间轴点时,标签旋转90度水平显示+左对齐最左边矩形的左边框
对于最右边的点,首先旋转90度以产生水平显示,然后将文本元素与最右边矩形的右边框右对齐。
对于所有的中间点,也先旋转90°水平显示,然后将文本相对于各自时间线点的中心居中对齐。
<text>
元素是使用提供的文本标签以编程方式生成的,因此它们可能包含 1 - 30 个字符的任意数字;导致可变宽度和高度。
示例
旋转从来没有像我期望的那样。例如,当我尝试通过将旋转原点设置为左下角并将旋转角度设置为 90 来旋转最左侧的 <text>
元素时,<text>
元素会旋转到顶部的顶部svg 的边框。不知道为什么。要重现它:
- 将
getBBox()
应用到文本元素上以获得其宽度W
。 - 将
W
+text
元素的y
属性的值相加得到那个最左边的左下角的y
坐标文本元素;Y
. - 将相应的旋转命令:
rotate(90,0,Y)
添加到最左侧文本元素的transform
元素中,您将得到: transform="rotate(-90,17,32) rotate(90,0,Y)
。旋转完全不符合您的预期...
示例 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 度,使其水平显示,其旋转原点位于文本元素的中心。因此,我首先按如下方式计算文本元素的中心:
使用
document.getElementsByTagName("text")[0].getBBox();
获取相关元素的维度。这个 returns 一个 SVG 矩形,高度为 16.38888931274414 个 SVG 单位,宽度为 36.10185241699219 个 SVG 单位。我现在计算文本元素中心的坐标,如下所示:
x = 25 - 16.38888931274414 / 2 = 大约。 16.81
y = 50 - 36.10185241699219 / 2 = 大约。 31.95
- 我现在在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>